summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Yi <byi@google.com>2015-11-20 16:47:03 -0800
committerBill Yi <byi@google.com>2015-11-20 16:47:03 -0800
commit89a5173601e7e2f68dbbd064a228ea6e4c7f2abf (patch)
treef539e9c8e48c9e24b843b715cc957f99cd6dd53d
parent9cbe78de6c99f9e31643eb32b6ad4fbe75fd30ba (diff)
parent01f41a46e8a9e0b8d4518aaf7aa757e83f4f938f (diff)
downloadtpm-89a5173601e7e2f68dbbd064a228ea6e4c7f2abf.tar.gz
Add 'trunks/' from commit '01f41a46e8a9e0b8d4518aaf7aa757e83f4f938f'brillo-m7-releasebrillo-m7-mr-devbrillo-m7-dev
git-subtree-dir: trunks git-subtree-mainline: 9cbe78de6c99f9e31643eb32b6ad4fbe75fd30ba git-subtree-split: 01f41a46e8a9e0b8d4518aaf7aa757e83f4f938f
-rw-r--r--trunks/CPPLINT.cfg1
-rw-r--r--trunks/MODULE_LICENSE_APACHE20
-rw-r--r--trunks/Makefile40
-rw-r--r--trunks/NOTICE190
-rw-r--r--trunks/OWNERS3
-rw-r--r--trunks/PRESUBMIT.cfg3
-rw-r--r--trunks/README52
-rw-r--r--trunks/authorization_delegate.h65
-rw-r--r--trunks/background_command_transceiver.cc108
-rw-r--r--trunks/background_command_transceiver.h79
-rw-r--r--trunks/background_command_transceiver_test.cc110
-rw-r--r--trunks/blob_parser.cc127
-rw-r--r--trunks/blob_parser.h66
-rw-r--r--trunks/command_transceiver.h54
-rw-r--r--trunks/dbus_interface.h31
-rw-r--r--trunks/dbus_interface.proto17
-rw-r--r--trunks/error_codes.cc239
-rw-r--r--trunks/error_codes.h87
-rw-r--r--trunks/ftdi/mpsse.c1153
-rw-r--r--trunks/ftdi/mpsse.h251
-rw-r--r--trunks/ftdi/support.c277
-rw-r--r--trunks/ftdi/support.h42
-rwxr-xr-xtrunks/generator/extract_commands.sh101
-rwxr-xr-xtrunks/generator/extract_structures.sh392
-rwxr-xr-xtrunks/generator/generator.py2092
-rwxr-xr-xtrunks/generator/generator_test.py256
-rw-r--r--trunks/generator/raw_commands.txt35656
-rw-r--r--trunks/generator/raw_commands_fixed.txt35665
-rw-r--r--trunks/generator/raw_structures.txt17797
-rw-r--r--trunks/generator/raw_structures_fixed.txt17774
-rw-r--r--trunks/generator/union_selectors.py192
-rw-r--r--trunks/hmac_authorization_delegate.cc325
-rw-r--r--trunks/hmac_authorization_delegate.h164
-rw-r--r--trunks/hmac_authorization_delegate_test.cc272
-rw-r--r--trunks/hmac_session.h71
-rw-r--r--trunks/hmac_session_impl.cc71
-rw-r--r--trunks/hmac_session_impl.h81
-rw-r--r--trunks/hmac_session_test.cc105
-rw-r--r--trunks/mock_authorization_delegate.cc24
-rw-r--r--trunks/mock_authorization_delegate.h49
-rw-r--r--trunks/mock_blob_parser.cc35
-rw-r--r--trunks/mock_blob_parser.h51
-rw-r--r--trunks/mock_command_transceiver.cc24
-rw-r--r--trunks/mock_command_transceiver.h44
-rw-r--r--trunks/mock_hmac_session.cc24
-rw-r--r--trunks/mock_hmac_session.h48
-rw-r--r--trunks/mock_policy_session.cc24
-rw-r--r--trunks/mock_policy_session.h53
-rw-r--r--trunks/mock_session_manager.cc30
-rw-r--r--trunks/mock_session_manager.h47
-rw-r--r--trunks/mock_tpm.cc255
-rw-r--r--trunks/mock_tpm.h1647
-rw-r--r--trunks/mock_tpm_state.cc45
-rw-r--r--trunks/mock_tpm_state.h52
-rw-r--r--trunks/mock_tpm_utility.cc24
-rw-r--r--trunks/mock_tpm_utility.h133
-rw-r--r--trunks/org.chromium.Trunks.conf15
-rw-r--r--trunks/password_authorization_delegate.cc95
-rw-r--r--trunks/password_authorization_delegate.h61
-rw-r--r--trunks/password_authorization_delegate_test.cc96
-rw-r--r--trunks/policy_session.h88
-rw-r--r--trunks/policy_session_impl.cc184
-rw-r--r--trunks/policy_session_impl.h85
-rw-r--r--trunks/policy_session_test.cc229
-rw-r--r--trunks/resource_manager.cc856
-rw-r--r--trunks/resource_manager.h238
-rw-r--r--trunks/resource_manager_test.cc894
-rw-r--r--trunks/scoped_key_handle.cc81
-rw-r--r--trunks/scoped_key_handle.h71
-rw-r--r--trunks/scoped_key_handle_test.cc94
-rw-r--r--trunks/session_manager.h73
-rw-r--r--trunks/session_manager_impl.cc210
-rw-r--r--trunks/session_manager_impl.h72
-rw-r--r--trunks/session_manager_test.cc169
-rw-r--r--trunks/tpm_constants.h45
-rw-r--r--trunks/tpm_generated.cc41014
-rw-r--r--trunks/tpm_generated.h6691
-rw-r--r--trunks/tpm_generated_test.cc440
-rw-r--r--trunks/tpm_handle.cc97
-rw-r--r--trunks/tpm_handle.h63
-rw-r--r--trunks/tpm_simulator_handle.cc115
-rw-r--r--trunks/tpm_simulator_handle.h65
-rw-r--r--trunks/tpm_state.h94
-rw-r--r--trunks/tpm_state_impl.cc246
-rw-r--r--trunks/tpm_state_impl.h78
-rw-r--r--trunks/tpm_state_test.cc384
-rw-r--r--trunks/tpm_utility.h304
-rw-r--r--trunks/tpm_utility_impl.cc1798
-rw-r--r--trunks/tpm_utility_impl.h202
-rw-r--r--trunks/tpm_utility_test.cc2004
-rw-r--r--trunks/trunks.gyp183
-rw-r--r--trunks/trunks_client.cc253
-rw-r--r--trunks/trunks_client_test.cc1058
-rw-r--r--trunks/trunks_client_test.h147
-rw-r--r--trunks/trunks_export.h24
-rw-r--r--trunks/trunks_factory.h81
-rw-r--r--trunks/trunks_factory_for_test.cc599
-rw-r--r--trunks/trunks_factory_for_test.h131
-rw-r--r--trunks/trunks_factory_impl.cc85
-rw-r--r--trunks/trunks_factory_impl.h68
-rw-r--r--trunks/trunks_ftdi_spi.cc344
-rw-r--r--trunks/trunks_ftdi_spi.h104
-rw-r--r--trunks/trunks_proxy.cc111
-rw-r--r--trunks/trunks_proxy.h66
-rw-r--r--trunks/trunks_service.cc71
-rw-r--r--trunks/trunks_service.h69
-rw-r--r--trunks/trunks_testrunner.cc31
-rw-r--r--trunks/trunksd-seccomp-amd64.policy74
-rw-r--r--trunks/trunksd-seccomp-arm.policy62
-rw-r--r--trunks/trunksd-seccomp-x86.policy54
-rw-r--r--trunks/trunksd.cc134
-rw-r--r--trunks/trunksd.conf24
112 files changed, 177642 insertions, 0 deletions
diff --git a/trunks/CPPLINT.cfg b/trunks/CPPLINT.cfg
new file mode 100644
index 0000000..206fce0
--- /dev/null
+++ b/trunks/CPPLINT.cfg
@@ -0,0 +1 @@
+exclude_files=tpm_generated\.(h|cc)
diff --git a/trunks/MODULE_LICENSE_APACHE2 b/trunks/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/trunks/MODULE_LICENSE_APACHE2
diff --git a/trunks/Makefile b/trunks/Makefile
new file mode 100644
index 0000000..9afcbd7
--- /dev/null
+++ b/trunks/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+PWD ?= $(CURDIR)
+OUT ?= $(PWD)/build-opt-local
+
+include common.mk
+
+PC_DEPS = libchrome-$(BASE_VER) libbrillo-$(BASE_VER) openssl
+PC_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(PC_DEPS))
+PC_LIBS := $(shell $(PKG_CONFIG) --libs $(PC_DEPS))
+
+CXXFLAGS += -I$(SRC)/.. $(PC_CFLAGS)
+LDLIBS += $(PC_LIBS)
+
+TEST_OBJS := $(filter %_test.o trunks_testrunner.o mock_%.o, $(CXX_OBJECTS))
+SHARED_OBJS := $(filter-out $(TEST_OBJS), $(CXX_OBJECTS))
+
+CXX_BINARY(trunks_testrunner): CXXFLAGS += $(shell gtest-config --cxxflags) \
+ $(shell gmock-config --cxxflags)
+CXX_BINARY(trunks_testrunner): LDLIBS += $(shell gtest-config --libs) \
+ $(shell gmock-config --libs)
+CXX_BINARY(trunks_testrunner): $(TEST_OBJS) $(SHARED_OBJS)
+
+all: $(SHARED_OBJS)
+tests: TEST(CXX_BINARY(trunks_testrunner))
+clean: CLEAN(CXX_BINARY(trunks_testrunner))
diff --git a/trunks/NOTICE b/trunks/NOTICE
new file mode 100644
index 0000000..a849a94
--- /dev/null
+++ b/trunks/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2014-2015, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ 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.
+
+
+ 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
+
diff --git a/trunks/OWNERS b/trunks/OWNERS
new file mode 100644
index 0000000..040e841
--- /dev/null
+++ b/trunks/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+dkrahn@chromium.org
+usanghi@chromium.org
diff --git a/trunks/PRESUBMIT.cfg b/trunks/PRESUBMIT.cfg
new file mode 100644
index 0000000..087dfa3
--- /dev/null
+++ b/trunks/PRESUBMIT.cfg
@@ -0,0 +1,3 @@
+[Hook Overrides]
+cros_license_check: false
+aosp_license_check: true
diff --git a/trunks/README b/trunks/README
new file mode 100644
index 0000000..6b3abca
--- /dev/null
+++ b/trunks/README
@@ -0,0 +1,52 @@
+======
+TRUNKS
+======
+
+The Trunks TPM Library (TTL) is a set of types and functions used to interface
+with a Trusted Platform Module. It is designed to be light, and does not
+comply with the TSS specification. It is usable in firmware as well as in
+user-level code.
+
+-----------------
+TPM SPECIFICATION
+-----------------
+
+See http://www.trustedcomputinggroup.org. This version of trunks is based on
+TPM 2.0 rev 00.99.
+
+--- Structures ---
+generator/raw_structures.txt
+generator/raw_structures_fixed.txt
+
+This file is a direct PDF scrape* of 'Part 2 - Structures'. The '_fixed'
+version includes some manual fixes to make processing easier.
+
+--- Commands ---
+generator/raw_commands.txt
+generator/raw_commands_fixed.txt
+
+This file is a direct PDF scrape* of 'Part 3 - Commands'. The '_fixed' version
+includes some manual fixes to make processing easier.
+
+---
+*Scraping for this version of trunks used Poppler's pdftotext utility v0.18.4.
+
+---------------
+CODE GENERATION
+---------------
+
+generator/extract_structures.sh
+
+Extracts structured information about types, constants, structures, and unions
+from spec/raw_structures_fixed.txt. The output of this script is intended to be
+parsed by generator.py.
+
+generator/extract_commands.sh
+
+Extracts structured information about commands from spec/raw_commands_fixed.txt.
+The output of this script is intended to be parsed by generator.py.
+
+generator/generator.py
+
+Generates C++ serialization and parsing code for TPM commands. Inputs must be
+formatted as by the extract_* scripts.
diff --git a/trunks/authorization_delegate.h b/trunks/authorization_delegate.h
new file mode 100644
index 0000000..f14a510
--- /dev/null
+++ b/trunks/authorization_delegate.h
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_AUTHORIZATION_DELEGATE_H_
+#define TRUNKS_AUTHORIZATION_DELEGATE_H_
+
+#include <string>
+
+#include <base/macros.h>
+
+namespace trunks {
+
+// AuthorizationDelegate is an interface passed to TPM commands. The delegate
+// takes care of providing the authorization data for commands and verifying
+// authorization data for responses. It also handles parameter encryption for
+// commands and parameter decryption for responses.
+class AuthorizationDelegate {
+ public:
+ AuthorizationDelegate() {}
+ virtual ~AuthorizationDelegate() {}
+
+ // Provides authorization data for a command which has a cpHash value of
+ // |command_hash|. The availability of encryption for the command is indicated
+ // by |is_*_parameter_encryption_possible|. On success, |authorization| is
+ // populated with the exact octets for the Authorization Area of the command.
+ // Returns true on success.
+ virtual bool GetCommandAuthorization(
+ const std::string& command_hash,
+ bool is_command_parameter_encryption_possible,
+ bool is_response_parameter_encryption_possible,
+ std::string* authorization) = 0;
+
+ // Checks authorization data for a response which has a rpHash value of
+ // |response_hash|. The exact octets from the Authorization Area of the
+ // response are given in |authorization|. Returns true iff the authorization
+ // is valid.
+ virtual bool CheckResponseAuthorization(const std::string& response_hash,
+ const std::string& authorization) = 0;
+
+ // Encrypts |parameter| if encryption is enabled. Returns true on success.
+ virtual bool EncryptCommandParameter(std::string* parameter) = 0;
+
+ // Decrypts |parameter| if encryption is enabled. Returns true on success.
+ virtual bool DecryptResponseParameter(std::string* parameter) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AuthorizationDelegate);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_AUTHORIZATION_DELEGATE_H_
diff --git a/trunks/background_command_transceiver.cc b/trunks/background_command_transceiver.cc
new file mode 100644
index 0000000..b344297
--- /dev/null
+++ b/trunks/background_command_transceiver.cc
@@ -0,0 +1,108 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/background_command_transceiver.h"
+
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/location.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop_proxy.h>
+#include <base/synchronization/waitable_event.h>
+
+namespace {
+
+// A simple callback useful when waiting for an asynchronous call.
+void AssignAndSignal(std::string* destination,
+ base::WaitableEvent* event,
+ const std::string& source) {
+ *destination = source;
+ event->Signal();
+}
+
+// A callback which posts another |callback| to a given |message_loop|.
+void PostCallbackToMessageLoop(
+ const trunks::CommandTransceiver::ResponseCallback& callback,
+ scoped_refptr<base::MessageLoopProxy> message_loop,
+ const std::string& response) {
+ base::Closure task = base::Bind(callback, response);
+ message_loop->PostTask(FROM_HERE, task);
+}
+
+} // namespace
+
+namespace trunks {
+
+BackgroundCommandTransceiver::BackgroundCommandTransceiver(
+ CommandTransceiver* next_transceiver,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner)
+ : next_transceiver_(next_transceiver),
+ task_runner_(task_runner),
+ weak_factory_(this) {}
+
+BackgroundCommandTransceiver::~BackgroundCommandTransceiver() {}
+
+void BackgroundCommandTransceiver::SendCommand(
+ const std::string& command,
+ const ResponseCallback& callback) {
+ if (task_runner_.get()) {
+ ResponseCallback background_callback = base::Bind(
+ PostCallbackToMessageLoop,
+ callback,
+ base::MessageLoopProxy::current());
+ // Use SendCommandTask instead of binding to next_transceiver_ directly to
+ // leverage weak pointer semantics.
+ base::Closure task = base::Bind(
+ &BackgroundCommandTransceiver::SendCommandTask,
+ GetWeakPtr(),
+ command,
+ background_callback);
+ task_runner_->PostNonNestableTask(FROM_HERE, task);
+ } else {
+ next_transceiver_->SendCommand(command, callback);
+ }
+}
+
+std::string BackgroundCommandTransceiver::SendCommandAndWait(
+ const std::string& command) {
+ if (task_runner_.get()) {
+ std::string response;
+ base::WaitableEvent response_ready(true, // manual_reset
+ false); // initially_signaled
+ ResponseCallback callback =
+ base::Bind(&AssignAndSignal, &response, &response_ready);
+ // Use SendCommandTask instead of binding to next_transceiver_ directly to
+ // leverage weak pointer semantics.
+ base::Closure task = base::Bind(
+ &BackgroundCommandTransceiver::SendCommandTask,
+ GetWeakPtr(),
+ command,
+ callback);
+ task_runner_->PostNonNestableTask(FROM_HERE, task);
+ response_ready.Wait();
+ return response;
+ } else {
+ return next_transceiver_->SendCommandAndWait(command);
+ }
+}
+
+void BackgroundCommandTransceiver::SendCommandTask(
+ const std::string& command,
+ const ResponseCallback& callback) {
+ next_transceiver_->SendCommand(command, callback);
+}
+
+} // namespace trunks
diff --git a/trunks/background_command_transceiver.h b/trunks/background_command_transceiver.h
new file mode 100644
index 0000000..048ff36
--- /dev/null
+++ b/trunks/background_command_transceiver.h
@@ -0,0 +1,79 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_BACKGROUND_COMMAND_TRANSCEIVER_H_
+#define TRUNKS_BACKGROUND_COMMAND_TRANSCEIVER_H_
+
+#include "trunks/command_transceiver.h"
+
+#include <string>
+
+#include <base/memory/ref_counted.h>
+#include <base/memory/weak_ptr.h>
+#include <base/sequenced_task_runner.h>
+
+namespace trunks {
+
+// Sends commands to another CommandTransceiver on a background thread. Response
+// callbacks are called on the original calling thread.
+// Example:
+// base::Thread background_thread("my thread");
+// ...
+// BackgroundCommandTransceiver background_transceiver(
+// next_transceiver,
+// background_thread.message_loop_proxy());
+// ...
+// background_transceiver.SendCommand(my_command, MyCallback);
+class BackgroundCommandTransceiver: public CommandTransceiver {
+ public:
+ // All commands will be forwarded to |next_transceiver| on |task_runner|,
+ // regardless of whether the synchronous or asynchronous method is used. This
+ // class will hold a reference count to |task_runner|. If |task_runner| is
+ // nullptr, all commands will be forwarded on the current thread. This class
+ // does not take ownership of |next_transceiver|; it must remain valid for
+ // the lifetime of the object.
+ explicit BackgroundCommandTransceiver(
+ CommandTransceiver* next_transceiver,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner);
+ ~BackgroundCommandTransceiver() override;
+
+ // CommandTranceiver methods.
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) override;
+ std::string SendCommandAndWait(const std::string& command) override;
+
+ private:
+ // Sends a |command| to the |next_transceiver_| and invokes a |callback| with
+ // the command response.
+ void SendCommandTask(const std::string& command,
+ const ResponseCallback& callback);
+
+ base::WeakPtr<BackgroundCommandTransceiver> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ CommandTransceiver* next_transceiver_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ // Declared last so weak pointers are invalidated first on destruction.
+ base::WeakPtrFactory<BackgroundCommandTransceiver> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundCommandTransceiver);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_BACKGROUND_COMMAND_TRANSCEIVER_H_
diff --git a/trunks/background_command_transceiver_test.cc b/trunks/background_command_transceiver_test.cc
new file mode 100644
index 0000000..be17f72
--- /dev/null
+++ b/trunks/background_command_transceiver_test.cc
@@ -0,0 +1,110 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/background_command_transceiver.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <base/run_loop.h>
+#include <base/threading/platform_thread.h>
+#include <base/threading/thread.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/command_transceiver.h"
+#include "trunks/mock_command_transceiver.h"
+
+using testing::_;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using testing::WithArgs;
+
+namespace {
+
+const char kTestThreadName[] = "test_thread";
+
+std::string GetThreadName() {
+ return std::string(base::PlatformThread::GetName());
+}
+
+void GetThreadNameAndCall(
+ const trunks::CommandTransceiver::ResponseCallback& callback) {
+ callback.Run(GetThreadName());
+}
+
+void Assign(std::string* to, const std::string& from) {
+ *to = from;
+}
+
+void SendCommandAndWaitAndAssign(trunks::CommandTransceiver* transceiver,
+ std::string* output) {
+ *output = transceiver->SendCommandAndWait("test");
+}
+
+} // namespace
+
+namespace trunks {
+
+class BackgroundTransceiverTest : public testing::Test {
+ public:
+ BackgroundTransceiverTest() : test_thread_(kTestThreadName) {
+ EXPECT_CALL(next_transceiver_, SendCommand(_, _))
+ .WillRepeatedly(WithArgs<1>(Invoke(GetThreadNameAndCall)));
+ EXPECT_CALL(next_transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(InvokeWithoutArgs(GetThreadName));
+ CHECK(test_thread_.Start());
+ }
+
+ ~BackgroundTransceiverTest() override {}
+
+ protected:
+ base::MessageLoopForIO message_loop_;
+ base::Thread test_thread_;
+ MockCommandTransceiver next_transceiver_;
+};
+
+TEST_F(BackgroundTransceiverTest, Asynchronous) {
+ trunks::BackgroundCommandTransceiver background_transceiver(
+ &next_transceiver_,
+ test_thread_.message_loop_proxy());
+ std::string output = "not_assigned";
+ background_transceiver.SendCommand("test", base::Bind(Assign, &output));
+ do {
+ base::RunLoop run_loop;
+ run_loop.RunUntilIdle();
+ } while (output == "not_assigned");
+ // The call to our mock should have happened on the background thread.
+ EXPECT_EQ(std::string(kTestThreadName), output);
+}
+
+TEST_F(BackgroundTransceiverTest, Synchronous) {
+ trunks::BackgroundCommandTransceiver background_transceiver(
+ &next_transceiver_,
+ test_thread_.message_loop_proxy());
+ std::string output = "not_assigned";
+ // Post a synchronous call to be run when we start pumping the loop.
+ message_loop_.PostTask(FROM_HERE,
+ base::Bind(SendCommandAndWaitAndAssign,
+ &background_transceiver,
+ &output));
+ base::RunLoop run_loop;
+ run_loop.RunUntilIdle();
+ // The call to our mock should have happened on the background thread.
+ EXPECT_EQ(std::string("test_thread"), output);
+}
+
+} // namespace trunks
diff --git a/trunks/blob_parser.cc b/trunks/blob_parser.cc
new file mode 100644
index 0000000..71f2014
--- /dev/null
+++ b/trunks/blob_parser.cc
@@ -0,0 +1,127 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/blob_parser.h"
+
+#include <base/logging.h>
+#include <base/stl_util.h>
+
+#include "trunks/error_codes.h"
+
+namespace trunks {
+
+bool BlobParser::SerializeKeyBlob(const TPM2B_PUBLIC& public_info,
+ const TPM2B_PRIVATE& private_info,
+ std::string* key_blob) {
+ CHECK(key_blob) << "KeyBlob not defined.";
+ key_blob->clear();
+ if ((public_info.size == 0) && (private_info.size == 0)) {
+ return true;
+ }
+ TPM_RC result = Serialize_TPM2B_PUBLIC(public_info, key_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing public info: " << GetErrorString(result);
+ return false;
+ }
+ result = Serialize_TPM2B_PRIVATE(private_info, key_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing private info: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool BlobParser::ParseKeyBlob(const std::string& key_blob,
+ TPM2B_PUBLIC* public_info,
+ TPM2B_PRIVATE* private_info) {
+ CHECK(public_info) << "Public info not defined.";
+ CHECK(private_info) << "Private info not defined.";
+ if (key_blob.empty()) {
+ public_info->size = 0;
+ private_info->size = 0;
+ return true;
+ }
+ std::string mutable_key_blob = key_blob;
+ TPM_RC result = Parse_TPM2B_PUBLIC(&mutable_key_blob, public_info, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error parsing public info: " << GetErrorString(result);
+ return false;
+ }
+ result = Parse_TPM2B_PRIVATE(&mutable_key_blob, private_info, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error parsing private info: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool BlobParser::SerializeCreationBlob(const TPM2B_CREATION_DATA& creation_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_TK_CREATION& creation_ticket,
+ std::string* creation_blob) {
+ CHECK(creation_blob) << "CreationBlob not defined.";
+ creation_blob->clear();
+ TPM_RC result = Serialize_TPM2B_CREATION_DATA(creation_data, creation_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing creation_data: " << GetErrorString(result);
+ return false;
+ }
+ result = Serialize_TPM2B_DIGEST(creation_hash, creation_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing creation_hash: " << GetErrorString(result);
+ return false;
+ }
+ result = Serialize_TPMT_TK_CREATION(creation_ticket, creation_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing creation_ticket: "
+ << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool BlobParser::ParseCreationBlob(const std::string& creation_blob,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket) {
+ CHECK(creation_data) << "CreationData not defined.";
+ CHECK(creation_hash) << "CreationHash not defined.";
+ CHECK(creation_ticket) << "CreationTicket not defined.";
+ if (creation_blob.empty()) {
+ return false;
+ }
+ std::string mutable_creation_blob = creation_blob;
+ TPM_RC result = Parse_TPM2B_CREATION_DATA(&mutable_creation_blob,
+ creation_data, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error parsing creation_data: " << GetErrorString(result);
+ return false;
+ }
+ result = Parse_TPM2B_DIGEST(&mutable_creation_blob, creation_hash, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error parsing creation_hash: " << GetErrorString(result);
+ return false;
+ }
+ result = Parse_TPMT_TK_CREATION(&mutable_creation_blob,
+ creation_ticket, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error parsing creation_ticket: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+} // namespace trunks
diff --git a/trunks/blob_parser.h b/trunks/blob_parser.h
new file mode 100644
index 0000000..b9c44b6
--- /dev/null
+++ b/trunks/blob_parser.h
@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_BLOB_PARSER_H_
+#define TRUNKS_BLOB_PARSER_H_
+
+#include <string>
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class TRUNKS_EXPORT BlobParser {
+ public:
+ BlobParser() = default;
+ virtual ~BlobParser() = default;
+
+ // This method is used to construct a |key_blob| given the associated key's
+ // TPM2B_PUBLIC and TPM2B_PRIVATE structs. Returns true on successful
+ // serialization, else false.
+ virtual bool SerializeKeyBlob(const TPM2B_PUBLIC& public_info,
+ const TPM2B_PRIVATE& private_info,
+ std::string* key_blob);
+
+ // This method returns the Public and Private structs associated with a given
+ // |key_blob|. Returns true on success, else false.
+ virtual bool ParseKeyBlob(const std::string& key_blob,
+ TPM2B_PUBLIC* public_info,
+ TPM2B_PRIVATE* private_info);
+
+ // This method is used to construct a |creation_blob| given the associated
+ // key's |creation_data|, |creation_hash| and |creation_ticket| structs.
+ // Returns true on successful serializtion, else false.
+ virtual bool SerializeCreationBlob(const TPM2B_CREATION_DATA& creation_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_TK_CREATION& creation_ticket,
+ std::string* creation_blob);
+
+ // This method returns the creation structures associated with a given
+ // |creation_blob|. Returns true on success, else false.
+ virtual bool ParseCreationBlob(const std::string& creation_blob,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BlobParser);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_BLOB_PARSER_H_
diff --git a/trunks/command_transceiver.h b/trunks/command_transceiver.h
new file mode 100644
index 0000000..00e4bef
--- /dev/null
+++ b/trunks/command_transceiver.h
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_COMMAND_TRANSCEIVER_H_
+#define TRUNKS_COMMAND_TRANSCEIVER_H_
+
+#include <string>
+
+#include <base/callback_forward.h>
+
+namespace trunks {
+
+// CommandTransceiver is an interface that sends commands to a TPM device and
+// receives responses. It can operate synchronously or asynchronously.
+class CommandTransceiver {
+ public:
+ typedef base::Callback<void(const std::string& response)> ResponseCallback;
+
+ virtual ~CommandTransceiver() {}
+
+ // Sends a TPM |command| asynchronously. When a |response| is received,
+ // |callback| will be called with the |response| data from the TPM. If a
+ // transmission error occurs |callback| will be called with a well-formed
+ // error |response|.
+ virtual void SendCommand(
+ const std::string& command,
+ const ResponseCallback& callback) = 0;
+
+ // Sends a TPM |command| synchronously (i.e. waits for a response) and returns
+ // the response. If a transmission error occurs the response will be populated
+ // with a well-formed error response.
+ virtual std::string SendCommandAndWait(const std::string& command) = 0;
+
+ // Initializes the actual interface, replaced by the derived classes, where
+ // needed.
+ virtual bool Init() { return true; }
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_COMMAND_TRANSCEIVER_H_
diff --git a/trunks/dbus_interface.h b/trunks/dbus_interface.h
new file mode 100644
index 0000000..ab67506
--- /dev/null
+++ b/trunks/dbus_interface.h
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_DBUS_INTERFACE_H_
+#define TRUNKS_DBUS_INTERFACE_H_
+
+namespace trunks {
+
+constexpr char kTrunksInterface[] = "org.chromium.Trunks";
+constexpr char kTrunksServicePath[] = "/org/chromium/Trunks";
+constexpr char kTrunksServiceName[] = "org.chromium.Trunks";
+
+// Methods exported by trunks.
+constexpr char kSendCommand[] = "SendCommand";
+
+}; // namespace trunks
+
+#endif // TRUNKS_DBUS_INTERFACE_H_
diff --git a/trunks/dbus_interface.proto b/trunks/dbus_interface.proto
new file mode 100644
index 0000000..c38b57a
--- /dev/null
+++ b/trunks/dbus_interface.proto
@@ -0,0 +1,17 @@
+option optimize_for = LITE_RUNTIME;
+package trunks;
+
+// The messages in this file correspond to the trunksd D-Bus interface. Each
+// exported method is represented here by a request and response protobuf.
+
+// Inputs for the SendCommand method.
+message SendCommandRequest {
+ // The raw bytes of a TPM command.
+ optional bytes command = 1;
+}
+
+// Outputs for the SendCommand method.
+message SendCommandResponse {
+ // The raw bytes of a TPM response.
+ optional bytes response = 1;
+}
diff --git a/trunks/error_codes.cc b/trunks/error_codes.cc
new file mode 100644
index 0000000..644fefa
--- /dev/null
+++ b/trunks/error_codes.cc
@@ -0,0 +1,239 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/error_codes.h"
+
+#include <sstream>
+#include <string>
+
+#include <base/logging.h>
+
+namespace {
+
+// Masks out the P and N bits (see TPM 2.0 Part 2 Table 14).
+const trunks::TPM_RC kFormatOneErrorMask = 0x0BF;
+// Selects just the N bits that identify the subject index.
+const trunks::TPM_RC kFormatOneSubjectMask = 0x700;
+const trunks::TPM_RC kLayerMask = 0xFFFFF000;
+
+// Returns a known error code or the empty string if unknown.
+std::string GetErrorStringInternal(trunks::TPM_RC error) {
+ switch (error) {
+ case trunks::TPM_RC_SUCCESS: return "TPM_RC_SUCCESS";
+ case trunks::TPM_RC_BAD_TAG: return "TPM_RC_BAD_TAG";
+ case trunks::TPM_RC_INITIALIZE: return "TPM_RC_INITIALIZE";
+ case trunks::TPM_RC_FAILURE: return "TPM_RC_FAILURE";
+ case trunks::TPM_RC_SEQUENCE: return "TPM_RC_SEQUENCE";
+ case trunks::TPM_RC_PRIVATE: return "TPM_RC_PRIVATE";
+ case trunks::TPM_RC_HMAC: return "TPM_RC_HMAC";
+ case trunks::TPM_RC_DISABLED: return "TPM_RC_DISABLED";
+ case trunks::TPM_RC_EXCLUSIVE: return "TPM_RC_EXCLUSIVE";
+ case trunks::TPM_RC_AUTH_TYPE: return "TPM_RC_AUTH_TYPE";
+ case trunks::TPM_RC_AUTH_MISSING: return "TPM_RC_AUTH_MISSING";
+ case trunks::TPM_RC_POLICY: return "TPM_RC_POLICY";
+ case trunks::TPM_RC_PCR: return "TPM_RC_PCR";
+ case trunks::TPM_RC_PCR_CHANGED: return "TPM_RC_PCR_CHANGED";
+ case trunks::TPM_RC_UPGRADE: return "TPM_RC_UPGRADE";
+ case trunks::TPM_RC_TOO_MANY_CONTEXTS: return "TPM_RC_TOO_MANY_CONTEXTS";
+ case trunks::TPM_RC_AUTH_UNAVAILABLE: return "TPM_RC_AUTH_UNAVAILABLE";
+ case trunks::TPM_RC_REBOOT: return "TPM_RC_REBOOT";
+ case trunks::TPM_RC_UNBALANCED: return "TPM_RC_UNBALANCED";
+ case trunks::TPM_RC_COMMAND_SIZE: return "TPM_RC_COMMAND_SIZE";
+ case trunks::TPM_RC_COMMAND_CODE: return "TPM_RC_COMMAND_CODE";
+ case trunks::TPM_RC_AUTHSIZE: return "TPM_RC_AUTHSIZE";
+ case trunks::TPM_RC_AUTH_CONTEXT: return "TPM_RC_AUTH_CONTEXT";
+ case trunks::TPM_RC_NV_RANGE: return "TPM_RC_NV_RANGE";
+ case trunks::TPM_RC_NV_SIZE: return "TPM_RC_NV_SIZE";
+ case trunks::TPM_RC_NV_LOCKED: return "TPM_RC_NV_LOCKED";
+ case trunks::TPM_RC_NV_AUTHORIZATION: return "TPM_RC_NV_AUTHORIZATION";
+ case trunks::TPM_RC_NV_UNINITIALIZED: return "TPM_RC_NV_UNINITIALIZED";
+ case trunks::TPM_RC_NV_SPACE: return "TPM_RC_NV_SPACE";
+ case trunks::TPM_RC_NV_DEFINED: return "TPM_RC_NV_DEFINED";
+ case trunks::TPM_RC_BAD_CONTEXT: return "TPM_RC_BAD_CONTEXT";
+ case trunks::TPM_RC_CPHASH: return "TPM_RC_CPHASH";
+ case trunks::TPM_RC_PARENT: return "TPM_RC_PARENT";
+ case trunks::TPM_RC_NEEDS_TEST: return "TPM_RC_NEEDS_TEST";
+ case trunks::TPM_RC_NO_RESULT: return "TPM_RC_NO_RESULT";
+ case trunks::TPM_RC_SENSITIVE: return "TPM_RC_SENSITIVE";
+ case trunks::TPM_RC_ASYMMETRIC: return "TPM_RC_ASYMMETRIC";
+ case trunks::TPM_RC_ATTRIBUTES: return "TPM_RC_ATTRIBUTES";
+ case trunks::TPM_RC_HASH: return "TPM_RC_HASH";
+ case trunks::TPM_RC_VALUE: return "TPM_RC_VALUE";
+ case trunks::TPM_RC_HIERARCHY: return "TPM_RC_HIERARCHY";
+ case trunks::TPM_RC_KEY_SIZE: return "TPM_RC_KEY_SIZE";
+ case trunks::TPM_RC_MGF: return "TPM_RC_MGF";
+ case trunks::TPM_RC_MODE: return "TPM_RC_MODE";
+ case trunks::TPM_RC_TYPE: return "TPM_RC_TYPE";
+ case trunks::TPM_RC_HANDLE: return "TPM_RC_HANDLE";
+ case trunks::TPM_RC_KDF: return "TPM_RC_KDF";
+ case trunks::TPM_RC_RANGE: return "TPM_RC_RANGE";
+ case trunks::TPM_RC_AUTH_FAIL: return "TPM_RC_AUTH_FAIL";
+ case trunks::TPM_RC_NONCE: return "TPM_RC_NONCE";
+ case trunks::TPM_RC_PP: return "TPM_RC_PP";
+ case trunks::TPM_RC_SCHEME: return "TPM_RC_SCHEME";
+ case trunks::TPM_RC_SIZE: return "TPM_RC_SIZE";
+ case trunks::TPM_RC_SYMMETRIC: return "TPM_RC_SYMMETRIC";
+ case trunks::TPM_RC_TAG: return "TPM_RC_TAG";
+ case trunks::TPM_RC_SELECTOR: return "TPM_RC_SELECTOR";
+ case trunks::TPM_RC_INSUFFICIENT: return "TPM_RC_INSUFFICIENT";
+ case trunks::TPM_RC_SIGNATURE: return "TPM_RC_SIGNATURE";
+ case trunks::TPM_RC_KEY: return "TPM_RC_KEY";
+ case trunks::TPM_RC_POLICY_FAIL: return "TPM_RC_POLICY_FAIL";
+ case trunks::TPM_RC_INTEGRITY: return "TPM_RC_INTEGRITY";
+ case trunks::TPM_RC_TICKET: return "TPM_RC_TICKET";
+ case trunks::TPM_RC_RESERVED_BITS: return "TPM_RC_RESERVED_BITS";
+ case trunks::TPM_RC_BAD_AUTH: return "TPM_RC_BAD_AUTH";
+ case trunks::TPM_RC_EXPIRED: return "TPM_RC_EXPIRED";
+ case trunks::TPM_RC_POLICY_CC: return "TPM_RC_POLICY_CC";
+ case trunks::TPM_RC_BINDING: return "TPM_RC_BINDING";
+ case trunks::TPM_RC_CURVE: return "TPM_RC_CURVE";
+ case trunks::TPM_RC_ECC_POINT: return "TPM_RC_ECC_POINT";
+ case trunks::TPM_RC_CONTEXT_GAP: return "TPM_RC_CONTEXT_GAP";
+ case trunks::TPM_RC_OBJECT_MEMORY: return "TPM_RC_OBJECT_MEMORY";
+ case trunks::TPM_RC_SESSION_MEMORY: return "TPM_RC_SESSION_MEMORY";
+ case trunks::TPM_RC_MEMORY: return "TPM_RC_MEMORY";
+ case trunks::TPM_RC_SESSION_HANDLES: return "TPM_RC_SESSION_HANDLES";
+ case trunks::TPM_RC_OBJECT_HANDLES: return "TPM_RC_OBJECT_HANDLES";
+ case trunks::TPM_RC_LOCALITY: return "TPM_RC_LOCALITY";
+ case trunks::TPM_RC_YIELDED: return "TPM_RC_YIELDED";
+ case trunks::TPM_RC_CANCELED: return "TPM_RC_CANCELED";
+ case trunks::TPM_RC_TESTING: return "TPM_RC_TESTING";
+ case trunks::TPM_RC_REFERENCE_H0: return "TPM_RC_REFERENCE_H0";
+ case trunks::TPM_RC_REFERENCE_H1: return "TPM_RC_REFERENCE_H1";
+ case trunks::TPM_RC_REFERENCE_H2: return "TPM_RC_REFERENCE_H2";
+ case trunks::TPM_RC_REFERENCE_H3: return "TPM_RC_REFERENCE_H3";
+ case trunks::TPM_RC_REFERENCE_H4: return "TPM_RC_REFERENCE_H4";
+ case trunks::TPM_RC_REFERENCE_H5: return "TPM_RC_REFERENCE_H5";
+ case trunks::TPM_RC_REFERENCE_H6: return "TPM_RC_REFERENCE_H6";
+ case trunks::TPM_RC_REFERENCE_S0: return "TPM_RC_REFERENCE_S0";
+ case trunks::TPM_RC_REFERENCE_S1: return "TPM_RC_REFERENCE_S1";
+ case trunks::TPM_RC_REFERENCE_S2: return "TPM_RC_REFERENCE_S2";
+ case trunks::TPM_RC_REFERENCE_S3: return "TPM_RC_REFERENCE_S3";
+ case trunks::TPM_RC_REFERENCE_S4: return "TPM_RC_REFERENCE_S4";
+ case trunks::TPM_RC_REFERENCE_S5: return "TPM_RC_REFERENCE_S5";
+ case trunks::TPM_RC_REFERENCE_S6: return "TPM_RC_REFERENCE_S6";
+ case trunks::TPM_RC_NV_RATE: return "TPM_RC_NV_RATE";
+ case trunks::TPM_RC_LOCKOUT: return "TPM_RC_LOCKOUT";
+ case trunks::TPM_RC_RETRY: return "TPM_RC_RETRY";
+ case trunks::TPM_RC_NV_UNAVAILABLE: return "TPM_RC_NV_UNAVAILABLE";
+ case trunks::TPM_RC_NOT_USED: return "TPM_RC_NOT_USED";
+ case trunks::TRUNKS_RC_AUTHORIZATION_FAILED:
+ return "TRUNKS_RC_AUTHORIZATION_FAILED";
+ case trunks::TRUNKS_RC_ENCRYPTION_FAILED:
+ return "TRUNKS_RC_ENCRYPTION_FAILED";
+ case trunks::TRUNKS_RC_READ_ERROR: return "TRUNKS_RC_READ_ERROR";
+ case trunks::TRUNKS_RC_WRITE_ERROR: return "TRUNKS_RC_WRITE_ERROR";
+ case trunks::TRUNKS_RC_IPC_ERROR: return "TRUNKS_RC_IPC_ERROR";
+ case trunks::TCTI_RC_TRY_AGAIN: return "TCTI_RC_TRY_AGAIN";
+ case trunks::TCTI_RC_GENERAL_FAILURE: return "TCTI_RC_GENERAL_FAILURE";
+ case trunks::TCTI_RC_BAD_CONTEXT: return "TCTI_RC_BAD_CONTEXT";
+ case trunks::TCTI_RC_WRONG_ABI_VERSION: return "TCTI_RC_WRONG_ABI_VERSION";
+ case trunks::TCTI_RC_NOT_IMPLEMENTED: return "TCTI_RC_NOT_IMPLEMENTED";
+ case trunks::TCTI_RC_BAD_PARAMETER: return "TCTI_RC_BAD_PARAMETER";
+ case trunks::TCTI_RC_INSUFFICIENT_BUFFER:
+ return "TCTI_RC_INSUFFICIENT_BUFFER";
+ case trunks::TCTI_RC_NO_CONNECTION: return "TCTI_RC_NO_CONNECTION";
+ case trunks::TCTI_RC_DRIVER_NOT_FOUND: return "TCTI_RC_DRIVER_NOT_FOUND";
+ case trunks::TCTI_RC_DRIVERINFO_NOT_FOUND:
+ return "TCTI_RC_DRIVERINFO_NOT_FOUND";
+ case trunks::TCTI_RC_NO_RESPONSE: return "TCTI_RC_NO_RESPONSE";
+ case trunks::TCTI_RC_BAD_VALUE: return "TCTI_RC_BAD_VALUE";
+ case trunks::SAPI_RC_INVALID_SESSIONS: return "SAPI_RC_INVALID_SESSIONS";
+ case trunks::SAPI_RC_ABI_MISMATCH: return "SAPI_RC_ABI_MISMATCH";
+ case trunks::SAPI_RC_INSUFFICIENT_BUFFER:
+ return "SAPI_RC_INSUFFICIENT_BUFFER";
+ case trunks::SAPI_RC_BAD_PARAMETER: return "SAPI_RC_BAD_PARAMETER";
+ case trunks::SAPI_RC_BAD_SEQUENCE: return "SAPI_RC_BAD_SEQUENCE";
+ case trunks::SAPI_RC_NO_DECRYPT_PARAM: return "SAPI_RC_NO_DECRYPT_PARAM";
+ case trunks::SAPI_RC_NO_ENCRYPT_PARAM: return "SAPI_RC_NO_ENCRYPT_PARAM";
+ case trunks::SAPI_RC_NO_RESPONSE_RECEIVED:
+ return "SAPI_RC_NO_RESPONSE_RECEIVED";
+ case trunks::SAPI_RC_BAD_SIZE: return "SAPI_RC_BAD_SIZE";
+ case trunks::SAPI_RC_CORRUPTED_DATA: return "SAPI_RC_CORRUPTED_DATA";
+ case trunks::SAPI_RC_INSUFFICIENT_CONTEXT:
+ return "SAPI_RC_INSUFFICIENT_CONTEXT";
+ case trunks::SAPI_RC_INSUFFICIENT_RESPONSE:
+ return "SAPI_RC_INSUFFICIENT_RESPONSE";
+ case trunks::SAPI_RC_INCOMPATIBLE_TCTI: return "SAPI_RC_INCOMPATIBLE_TCTI";
+ case trunks::SAPI_RC_MALFORMED_RESPONSE:
+ return "SAPI_RC_MALFORMED_RESPONSE";
+ case trunks::SAPI_RC_BAD_TCTI_STRUCTURE:
+ return "SAPI_RC_BAD_TCTI_STRUCTURE";
+ default: return std::string();
+ }
+ NOTREACHED();
+ return std::string();
+}
+
+bool IsFormatOne(trunks::TPM_RC error) {
+ return (error & kLayerMask) == 0 && (error & trunks::RC_FMT1) != 0;
+}
+
+} // namespace
+
+namespace trunks {
+
+std::string GetErrorString(TPM_RC error) {
+ std::string error_string = GetErrorStringInternal(error);
+ if (!error_string.empty()) {
+ return error_string;
+ }
+ std::stringstream ss;
+ if ((error & kLayerMask) == kResourceManagerTpmErrorBase) {
+ error &= ~kLayerMask;
+ error_string = GetErrorStringInternal(error);
+ ss << "Resource Manager: ";
+ }
+ // Check if we have a TPM 'Format-One' response code.
+ if (IsFormatOne(error)) {
+ if (error & TPM_RC_P) {
+ ss << "Parameter ";
+ } else if (error & TPM_RC_S) {
+ ss << "Session ";
+ } else {
+ ss << "Handle ";
+ }
+ // Bits 8-10 specify which handle / parameter / session.
+ ss << ((error & kFormatOneSubjectMask) >> 8) << ": ";
+ // Mask out everything but the format bit and error number.
+ error_string = GetErrorStringInternal(error & kFormatOneErrorMask);
+ if (!error_string.empty()) {
+ ss << error_string;
+ }
+ }
+ if (error_string.empty()) {
+ ss << "Unknown error: " << error << " (0x" << std::hex << error << ")";
+ }
+ return ss.str();
+}
+
+TPM_RC GetFormatOneError(TPM_RC error) {
+ if (IsFormatOne(error)) {
+ return (error & kFormatOneErrorMask);
+ }
+ return error;
+}
+
+std::string CreateErrorResponse(TPM_RC error_code) {
+ const uint32_t kErrorResponseSize = 10;
+ std::string response;
+ CHECK_EQ(Serialize_TPM_ST(TPM_ST_NO_SESSIONS, &response), TPM_RC_SUCCESS);
+ CHECK_EQ(Serialize_UINT32(kErrorResponseSize, &response), TPM_RC_SUCCESS);
+ CHECK_EQ(Serialize_TPM_RC(error_code, &response), TPM_RC_SUCCESS);
+ return response;
+}
+
+} // namespace trunks
diff --git a/trunks/error_codes.h b/trunks/error_codes.h
new file mode 100644
index 0000000..dd3b5b4
--- /dev/null
+++ b/trunks/error_codes.h
@@ -0,0 +1,87 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_ERROR_CODES_H_
+#define TRUNKS_ERROR_CODES_H_
+
+#include <string>
+
+#include "trunks/tpm_generated.h" // For TPM_RC.
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+// Use the TPM_RC type but with different layer bits (12 - 15). Choose the layer
+// value arbitrarily. Currently TSS2 uses 9 for TCTI and 8 for SAPI.
+// TCTI and SAPI error codes taken from
+// http://www.trustedcomputinggroup.org/resources/
+// tss_system_level_api_and_tpm_command_transmission_interface_specification
+const TPM_RC kTrunksErrorBase = (7 << 12);
+const TPM_RC kTctiErrorBase = (8 << 12);
+const TPM_RC kSapiErrorBase = (9 << 12);
+const TPM_RC kResourceManagerTpmErrorBase = (11 << 12);
+const TPM_RC kResourceManagerErrorBase = (12 << 12);
+
+const TPM_RC TRUNKS_RC_AUTHORIZATION_FAILED = kTrunksErrorBase + 1;
+const TPM_RC TRUNKS_RC_ENCRYPTION_FAILED = kTrunksErrorBase + 2;
+const TPM_RC TRUNKS_RC_READ_ERROR = kTrunksErrorBase + 3;
+const TPM_RC TRUNKS_RC_WRITE_ERROR = kTrunksErrorBase + 4;
+const TPM_RC TRUNKS_RC_IPC_ERROR = kTrunksErrorBase + 5;
+
+const TPM_RC TCTI_RC_TRY_AGAIN = kTctiErrorBase + 1;
+const TPM_RC TCTI_RC_GENERAL_FAILURE = kTctiErrorBase + 2;
+const TPM_RC TCTI_RC_BAD_CONTEXT = kTctiErrorBase + 3;
+const TPM_RC TCTI_RC_WRONG_ABI_VERSION = kTctiErrorBase + 4;
+const TPM_RC TCTI_RC_NOT_IMPLEMENTED = kTctiErrorBase + 5;
+const TPM_RC TCTI_RC_BAD_PARAMETER = kTctiErrorBase + 6;
+const TPM_RC TCTI_RC_INSUFFICIENT_BUFFER = kTctiErrorBase + 7;
+const TPM_RC TCTI_RC_NO_CONNECTION = kTctiErrorBase + 8;
+const TPM_RC TCTI_RC_DRIVER_NOT_FOUND = kTctiErrorBase + 9;
+const TPM_RC TCTI_RC_DRIVERINFO_NOT_FOUND = kTctiErrorBase + 10;
+const TPM_RC TCTI_RC_NO_RESPONSE = kTctiErrorBase + 11;
+const TPM_RC TCTI_RC_BAD_VALUE = kTctiErrorBase + 12;
+
+const TPM_RC SAPI_RC_INVALID_SESSIONS = kSapiErrorBase + 1;
+const TPM_RC SAPI_RC_ABI_MISMATCH = kSapiErrorBase + 2;
+const TPM_RC SAPI_RC_INSUFFICIENT_BUFFER = kSapiErrorBase + 3;
+const TPM_RC SAPI_RC_BAD_PARAMETER = kSapiErrorBase + 4;
+const TPM_RC SAPI_RC_BAD_SEQUENCE = kSapiErrorBase + 5;
+const TPM_RC SAPI_RC_NO_DECRYPT_PARAM = kSapiErrorBase + 6;
+const TPM_RC SAPI_RC_NO_ENCRYPT_PARAM = kSapiErrorBase + 7;
+const TPM_RC SAPI_RC_NO_RESPONSE_RECEIVED = kSapiErrorBase + 8;
+const TPM_RC SAPI_RC_BAD_SIZE = kSapiErrorBase + 9;
+const TPM_RC SAPI_RC_CORRUPTED_DATA = kSapiErrorBase + 10;
+const TPM_RC SAPI_RC_INSUFFICIENT_CONTEXT = kSapiErrorBase + 11;
+const TPM_RC SAPI_RC_INSUFFICIENT_RESPONSE = kSapiErrorBase + 12;
+const TPM_RC SAPI_RC_INCOMPATIBLE_TCTI = kSapiErrorBase + 13;
+const TPM_RC SAPI_RC_MALFORMED_RESPONSE = kSapiErrorBase + 14;
+const TPM_RC SAPI_RC_BAD_TCTI_STRUCTURE = kSapiErrorBase + 15;
+
+// Returns a description of |error|.
+TRUNKS_EXPORT std::string GetErrorString(TPM_RC error);
+
+// Strips the P and N bits from a 'format one' error. If the given error code
+// is not a format one error, it is returned as is. The error that is returned
+// can be compared to TPM_RC_* constant values. See TPM 2.0 Part 2 Section 6.6
+// for details on format one errors.
+TRUNKS_EXPORT TPM_RC GetFormatOneError(TPM_RC error);
+
+// Creates a well-formed response with the given |error_code|.
+TRUNKS_EXPORT std::string CreateErrorResponse(TPM_RC error_code);
+
+} // namespace trunks
+
+#endif // TRUNKS_ERROR_CODES_H_
diff --git a/trunks/ftdi/mpsse.c b/trunks/ftdi/mpsse.c
new file mode 100644
index 0000000..5171324
--- /dev/null
+++ b/trunks/ftdi/mpsse.c
@@ -0,0 +1,1153 @@
+/*
+/*
+/*Copyright (C) 2015 The Android Open Source Project
+/*
+/*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.
+ */
+ *
+ * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
+ * f1a6744b), and modified to suite the Chromium OS project.
+ *
+ * Main libmpsse source file.
+ *
+ * Craig Heffner
+ * 27 December 2011
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "trunks/ftdi/support.h"
+
+/* List of known FT2232-based devices */
+struct vid_pid supported_devices[] = {
+ {0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd"},
+ {0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd"},
+ {0x0403, 0x6014, "FT232H Future Technology Devices International, Ltd"},
+
+ /* These devices are based on FT2232 chips, but have not been tested. */
+ {0x0403, 0x8878, "Bus Blaster v2 (channel A)"},
+ {0x0403, 0x8879, "Bus Blaster v2 (channel B)"},
+ {0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A"},
+ {0x0403, 0xCFF8, "Amontec JTAGkey"},
+ {0x0403, 0x8A98, "TIAO Multi Protocol Adapter"},
+ {0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG"},
+ {0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY"},
+
+ {0, 0, NULL}};
+
+/*
+ * Opens and initializes the first FTDI device found.
+ *
+ * @mode - Mode to open the device in. One of enum modes.
+ * @freq - Clock frequency to use for the specified mode.
+ * @endianess - Specifies how data is clocked in/out (MSB, LSB).
+ *
+ * Returns a pointer to an MPSSE context structure if succeeded, NULL otherwise.
+ */
+struct mpsse_context* MPSSE(enum modes mode, int freq, int endianess) {
+ int i = 0;
+ struct mpsse_context* mpsse = NULL;
+
+ for (i = 0; supported_devices[i].vid != 0; i++) {
+ mpsse = Open(supported_devices[i].vid, supported_devices[i].pid, mode,
+ freq, endianess, IFACE_A, NULL, NULL);
+ if (mpsse) {
+ mpsse->description = supported_devices[i].description;
+ return mpsse;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Open device by VID/PID
+ *
+ * @vid - Device vendor ID.
+ * @pid - Device product ID.
+ * @mode - MPSSE mode, one of enum modes.
+ * @freq - Clock frequency to use for the specified mode.
+ * @endianess - Specifies how data is clocked in/out (MSB, LSB).
+ * @interface - FTDI interface to use (IFACE_A - IFACE_D).
+ * @description - Device product description (set to NULL if not needed).
+ * @serial - Device serial number (set to NULL if not needed).
+ *
+ * Returns a pointer to an MPSSE context structure on success.
+ */
+struct mpsse_context* Open(int vid,
+ int pid,
+ enum modes mode,
+ int freq,
+ int endianess,
+ int interface,
+ const char* description,
+ const char* serial) {
+ return OpenIndex(vid, pid, mode, freq, endianess, interface, description,
+ serial, 0);
+}
+
+/*
+ * Open device by VID/PID/index
+ *
+ * @vid - Device vendor ID.
+ * @pid - Device product ID.
+ * @mode - MPSSE mode, one of enum modes.
+ * @freq - Clock frequency to use for the specified mode.
+ * @endianess - Specifies how data is clocked in/out (MSB, LSB).
+ * @interface - FTDI interface to use (IFACE_A - IFACE_D).
+ * @description - Device product description (set to NULL if not needed).
+ * @serial - Device serial number (set to NULL if not needed).
+ * @index - Device index (set to 0 if not needed).
+ *
+ * Returns a pointer to an MPSSE context structure.
+ * On success, mpsse->open will be set to 1.
+ * On failure, mpsse->open will be set to 0.
+ */
+struct mpsse_context* OpenIndex(int vid,
+ int pid,
+ enum modes mode,
+ int freq,
+ int endianess,
+ int interface,
+ const char* description,
+ const char* serial,
+ int index) {
+ int status = 0;
+ struct mpsse_context* mpsse = NULL;
+
+ mpsse = malloc(sizeof(struct mpsse_context));
+ if (!mpsse)
+ return NULL;
+
+ memset(mpsse, 0, sizeof(struct mpsse_context));
+
+ /* Legacy; flushing is no longer needed, so disable it by default. */
+ FlushAfterRead(mpsse, 0);
+
+ /* ftdilib initialization */
+ if (ftdi_init(&mpsse->ftdi)) {
+ free(mpsse);
+ return NULL;
+ }
+
+ /* Set the FTDI interface */
+ ftdi_set_interface(&mpsse->ftdi, interface);
+
+ /* Open the specified device */
+ if (!ftdi_usb_open_desc_index(&mpsse->ftdi, vid, pid, description, serial,
+ index)) {
+ mpsse->mode = mode;
+ mpsse->vid = vid;
+ mpsse->pid = pid;
+ mpsse->status = STOPPED;
+ mpsse->endianess = endianess;
+
+ /* Set the appropriate transfer size for the requested protocol */
+ if (mpsse->mode == I2C)
+ mpsse->xsize = I2C_TRANSFER_SIZE;
+ else
+ mpsse->xsize = SPI_RW_SIZE;
+
+ status |= ftdi_usb_reset(&mpsse->ftdi);
+ status |= ftdi_set_latency_timer(&mpsse->ftdi, LATENCY_MS);
+ status |= ftdi_write_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE);
+ status |= ftdi_read_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE);
+ status |= ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET);
+
+ if (status == 0) {
+ /* Set the read and write timeout periods */
+ set_timeouts(mpsse, USB_TIMEOUT);
+
+ if (mpsse->mode != BITBANG) {
+ ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_MPSSE);
+
+ if (SetClock(mpsse, freq) == MPSSE_OK) {
+ if (SetMode(mpsse, endianess) == MPSSE_OK) {
+ mpsse->opened = 1;
+
+ /* Give the chip a few mS to initialize */
+ usleep(SETUP_DELAY);
+
+ /*
+ * Not all FTDI chips support all the commands that SetMode may
+ * have sent.
+ * This clears out any errors from unsupported commands that
+ * might have been sent during set up.
+ */
+ ftdi_usb_purge_buffers(&mpsse->ftdi);
+ }
+ }
+ } else {
+ /* Skip the setup functions if we're just operating in BITBANG mode
+ */
+ if (!ftdi_set_bitmode(&mpsse->ftdi, 0xFF, BITMODE_BITBANG))
+ mpsse->opened = 1;
+ }
+ }
+ }
+
+ if (mpsse && !mpsse->opened) {
+ Close(mpsse);
+ mpsse = NULL;
+ }
+
+ return mpsse;
+}
+
+/*
+ * Closes the device, deinitializes libftdi, and frees the MPSSE context
+ *pointer.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns void.
+ */
+void Close(struct mpsse_context* mpsse) {
+ if (!mpsse)
+ return;
+
+ if (mpsse->opened) {
+ /* Shut these down only if initialization succeeded before. */
+ ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET);
+ ftdi_usb_close(&mpsse->ftdi);
+ }
+ ftdi_deinit(&mpsse->ftdi);
+ free(mpsse);
+}
+
+/* Enables bit-wise data transfers.
+ * Must be called after MPSSE() / Open() / OpenIndex().
+ *
+ * Returns void.
+ */
+void EnableBitmode(struct mpsse_context* mpsse, int tf) {
+ if (is_valid_context(mpsse)) {
+ if (tf) {
+ mpsse->tx |= MPSSE_BITMODE;
+ mpsse->rx |= MPSSE_BITMODE;
+ mpsse->txrx |= MPSSE_BITMODE;
+ } else {
+ mpsse->tx &= ~MPSSE_BITMODE;
+ mpsse->rx &= ~MPSSE_BITMODE;
+ mpsse->txrx &= ~MPSSE_BITMODE;
+ }
+ }
+}
+
+/*
+ * Sets the appropriate transmit and receive commands based on the requested
+ *mode and byte order.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @endianess - MPSSE_MSB or MPSSE_LSB.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int SetMode(struct mpsse_context* mpsse, int endianess) {
+ int retval = MPSSE_OK, i = 0, setup_commands_size = 0;
+ uint8_t buf[CMD_SIZE] = {0};
+ uint8_t setup_commands[CMD_SIZE * MAX_SETUP_COMMANDS] = {0};
+
+ /* Do not call is_valid_context() here, as the FTDI chip may not be completely
+ * configured when SetMode is called */
+ if (mpsse) {
+ /* Read and write commands need to include endianess */
+ mpsse->tx = MPSSE_DO_WRITE | endianess;
+ mpsse->rx = MPSSE_DO_READ | endianess;
+ mpsse->txrx = MPSSE_DO_WRITE | MPSSE_DO_READ | endianess;
+
+ /* Clock, data out, chip select pins are outputs; all others are inputs. */
+ mpsse->tris = DEFAULT_TRIS;
+
+ /* Clock and chip select pins idle high; all others are low */
+ mpsse->pidle = mpsse->pstart = mpsse->pstop = DEFAULT_PORT;
+
+ /* During reads and writes the chip select pin is brought low */
+ mpsse->pstart &= ~CS;
+
+ /* Disable FTDI internal loopback */
+ SetLoopback(mpsse, 0);
+
+ /* Send ACKs by default */
+ SetAck(mpsse, ACK);
+
+ /* Ensure adaptive clock is disabled */
+ setup_commands[setup_commands_size++] = DISABLE_ADAPTIVE_CLOCK;
+
+ switch (mpsse->mode) {
+ case SPI0:
+ /* SPI mode 0 clock idles low */
+ mpsse->pidle &= ~SK;
+ mpsse->pstart &= ~SK;
+ mpsse->pstop &= ~SK;
+ /* SPI mode 0 propogates data on the falling edge and read data on the
+ * rising edge of the clock */
+ mpsse->tx |= MPSSE_WRITE_NEG;
+ mpsse->rx &= ~MPSSE_READ_NEG;
+ mpsse->txrx |= MPSSE_WRITE_NEG;
+ mpsse->txrx &= ~MPSSE_READ_NEG;
+ break;
+ case SPI3:
+ /* SPI mode 3 clock idles high */
+ mpsse->pidle |= SK;
+ mpsse->pstart |= SK;
+ /* Keep the clock low while the CS pin is brought high to ensure we
+ * don't accidentally clock out an extra bit */
+ mpsse->pstop &= ~SK;
+ /* SPI mode 3 propogates data on the falling edge and read data on the
+ * rising edge of the clock */
+ mpsse->tx |= MPSSE_WRITE_NEG;
+ mpsse->rx &= ~MPSSE_READ_NEG;
+ mpsse->txrx |= MPSSE_WRITE_NEG;
+ mpsse->txrx &= ~MPSSE_READ_NEG;
+ break;
+ case SPI1:
+ /* SPI mode 1 clock idles low */
+ mpsse->pidle &= ~SK;
+ /* Since this mode idles low, the start condition should ensure that the
+ * clock is low */
+ mpsse->pstart &= ~SK;
+ /* Even though we idle low in this mode, we need to keep the clock line
+ * high when we set the CS pin high to prevent
+ * an unintended clock cycle from being sent by the FT2232. This way,
+ * the clock goes high, but does not go low until
+ * after the CS pin goes high.
+ */
+ mpsse->pstop |= SK;
+ /* Data read on falling clock edge */
+ mpsse->rx |= MPSSE_READ_NEG;
+ mpsse->tx &= ~MPSSE_WRITE_NEG;
+ mpsse->txrx |= MPSSE_READ_NEG;
+ mpsse->txrx &= ~MPSSE_WRITE_NEG;
+ break;
+ case SPI2:
+ /* SPI 2 clock idles high */
+ mpsse->pidle |= SK;
+ mpsse->pstart |= SK;
+ mpsse->pstop |= SK;
+ /* Data read on falling clock edge */
+ mpsse->rx |= MPSSE_READ_NEG;
+ mpsse->tx &= ~MPSSE_WRITE_NEG;
+ mpsse->txrx |= MPSSE_READ_NEG;
+ mpsse->txrx &= ~MPSSE_WRITE_NEG;
+ break;
+ case I2C:
+ /* I2C propogates data on the falling clock edge and reads data on the
+ * falling (or rising) clock edge */
+ mpsse->tx |= MPSSE_WRITE_NEG;
+ mpsse->rx &= ~MPSSE_READ_NEG;
+ /* In I2C, both the clock and the data lines idle high */
+ mpsse->pidle |= DO | DI;
+ /* I2C start bit == data line goes from high to low while clock line is
+ * high */
+ mpsse->pstart &= ~DO & ~DI;
+ /* I2C stop bit == data line goes from low to high while clock line is
+ * high - set data line low here, so the transition to the idle state
+ * triggers the stop condition. */
+ mpsse->pstop &= ~DO & ~DI;
+ /* Enable three phase clock to ensure that I2C data is available on both
+ * the rising and falling clock edges */
+ setup_commands[setup_commands_size++] = ENABLE_3_PHASE_CLOCK;
+ break;
+ case GPIO:
+ break;
+ default:
+ retval = MPSSE_FAIL;
+ }
+
+ /* Send any setup commands to the chip */
+ if (retval == MPSSE_OK && setup_commands_size > 0) {
+ retval = raw_write(mpsse, setup_commands, setup_commands_size);
+ }
+
+ if (retval == MPSSE_OK) {
+ /* Set the idle pin states */
+ set_bits_low(mpsse, mpsse->pidle);
+
+ /* All GPIO pins are outputs, set low */
+ mpsse->trish = 0xFF;
+ mpsse->gpioh = 0x00;
+
+ buf[i++] = SET_BITS_HIGH;
+ buf[i++] = mpsse->gpioh;
+ buf[i++] = mpsse->trish;
+
+ retval = raw_write(mpsse, buf, i);
+ }
+ } else {
+ retval = MPSSE_FAIL;
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the appropriate divisor for the desired clock frequency.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @freq - Desired clock frequency in hertz.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int SetClock(struct mpsse_context* mpsse, uint32_t freq) {
+ int retval = MPSSE_FAIL;
+ uint32_t system_clock = 0;
+ uint16_t divisor = 0;
+ uint8_t buf[CMD_SIZE] = {0};
+
+ /* Do not call is_valid_context() here, as the FTDI chip may not be completely
+ * configured when SetClock is called */
+ if (mpsse) {
+ if (freq > SIX_MHZ) {
+ buf[0] = TCK_X5;
+ system_clock = SIXTY_MHZ;
+ } else {
+ buf[0] = TCK_D5;
+ system_clock = TWELVE_MHZ;
+ }
+
+ if (raw_write(mpsse, buf, 1) == MPSSE_OK) {
+ if (freq <= 0) {
+ divisor = 0xFFFF;
+ } else {
+ divisor = freq2div(system_clock, freq);
+ }
+
+ buf[0] = TCK_DIVISOR;
+ buf[1] = (divisor & 0xFF);
+ buf[2] = ((divisor >> 8) & 0xFF);
+
+ if (raw_write(mpsse, buf, 3) == MPSSE_OK) {
+ mpsse->clock = div2freq(system_clock, divisor);
+ retval = MPSSE_OK;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * Retrieves the last error string from libftdi.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns a pointer to the last error string.
+ */
+const char* ErrorString(struct mpsse_context* mpsse) {
+ if (mpsse != NULL) {
+ return ftdi_get_error_string(&mpsse->ftdi);
+ }
+
+ return NULL_CONTEXT_ERROR_MSG;
+}
+
+/*
+ * Gets the currently configured clock rate.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns the existing clock rate in hertz.
+ */
+int GetClock(struct mpsse_context* mpsse) {
+ int clock = 0;
+
+ if (is_valid_context(mpsse)) {
+ clock = mpsse->clock;
+ }
+
+ return clock;
+}
+
+/*
+ * Returns the vendor ID of the FTDI chip.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns the integer value of the vendor ID.
+ */
+int GetVid(struct mpsse_context* mpsse) {
+ int vid = 0;
+
+ if (is_valid_context(mpsse)) {
+ vid = mpsse->vid;
+ }
+
+ return vid;
+}
+
+/*
+ * Returns the product ID of the FTDI chip.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns the integer value of the product ID.
+ */
+int GetPid(struct mpsse_context* mpsse) {
+ int pid = 0;
+
+ if (is_valid_context(mpsse)) {
+ pid = mpsse->pid;
+ }
+
+ return pid;
+}
+
+/*
+ * Returns the description of the FTDI chip, if any.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns the description of the FTDI chip.
+ */
+const char* GetDescription(struct mpsse_context* mpsse) {
+ char* description = NULL;
+
+ if (is_valid_context(mpsse)) {
+ description = mpsse->description;
+ }
+
+ return description;
+}
+
+/*
+ * Enable / disable internal loopback.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @enable - Zero to disable loopback, 1 to enable loopback.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int SetLoopback(struct mpsse_context* mpsse, int enable) {
+ uint8_t buf[1] = {0};
+ int retval = MPSSE_FAIL;
+
+ if (is_valid_context(mpsse)) {
+ if (enable) {
+ buf[0] = LOOPBACK_START;
+ } else {
+ buf[0] = LOOPBACK_END;
+ }
+
+ retval = raw_write(mpsse, buf, 1);
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the idle state of the chip select pin. CS idles high by default.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @idle - Set to 1 to idle high, 0 to idle low.
+ *
+ * Returns void.
+ */
+void SetCSIdle(struct mpsse_context* mpsse, int idle) {
+ if (is_valid_context(mpsse)) {
+ if (idle > 0) {
+ /* Chip select idles high, active low */
+ mpsse->pidle |= CS;
+ mpsse->pstop |= CS;
+ mpsse->pstart &= ~CS;
+ } else {
+ /* Chip select idles low, active high */
+ mpsse->pidle &= ~CS;
+ mpsse->pstop &= ~CS;
+ mpsse->pstart |= CS;
+ }
+ }
+
+ return;
+}
+
+/*
+ * Enables or disables flushing of the FTDI chip's RX buffers after each read
+ *operation.
+ * Flushing is disable by default.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @tf - Set to 1 to enable flushing, or 0 to disable flushing.
+ *
+ * Returns void.
+ */
+void FlushAfterRead(struct mpsse_context* mpsse, int tf) {
+ mpsse->flush_after_read = tf;
+ return;
+}
+
+/*
+ * Send data start condition.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int Start(struct mpsse_context* mpsse) {
+ int status = MPSSE_OK;
+
+ if (is_valid_context(mpsse)) {
+ if (mpsse->mode == I2C && mpsse->status == STARTED) {
+ /* Set the default pin states while the clock is low since this is an I2C
+ * repeated start condition */
+ status |= set_bits_low(mpsse, (mpsse->pidle & ~SK));
+
+ /* Make sure the pins are in their default idle state */
+ status |= set_bits_low(mpsse, mpsse->pidle);
+ }
+
+ /* Set the start condition */
+ status |= set_bits_low(mpsse, mpsse->pstart);
+
+ /*
+ * Hackish work around to properly support SPI mode 3.
+ * SPI3 clock idles high, but needs to be set low before sending out
+ * data to prevent unintenteded clock glitches from the FT2232.
+ */
+ if (mpsse->mode == SPI3) {
+ status |= set_bits_low(mpsse, (mpsse->pstart & ~SK));
+ }
+ /*
+ * Hackish work around to properly support SPI mode 1.
+ * SPI1 clock idles low, but needs to be set high before sending out
+ * data to preven unintended clock glitches from the FT2232.
+ */
+ else if (mpsse->mode == SPI1) {
+ status |= set_bits_low(mpsse, (mpsse->pstart | SK));
+ }
+
+ mpsse->status = STARTED;
+ } else {
+ status = MPSSE_FAIL;
+ mpsse->status = STOPPED;
+ }
+
+ return status;
+}
+
+/*
+ * Performs a bit-wise write of up to 8 bits at a time.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @bits - A byte containing the desired bits to write.
+ * @size - The number of bits from the 'bits' byte to write.
+ *
+ * Returns MPSSE_OK on success, MPSSE_FAIL on failure.
+ */
+int WriteBits(struct mpsse_context* mpsse, char bits, size_t size) {
+ uint8_t data[8] = {0};
+ size_t i = 0;
+ int retval = MPSSE_OK;
+
+ if (size > sizeof(data)) {
+ size = sizeof(data);
+ }
+
+ /* Convert each bit in bits to an array of bytes */
+ for (i = 0; i < size; i++) {
+ if (bits & (1 << i)) {
+ /* Be sure to honor endianess */
+ if (mpsse->endianess == LSB) {
+ data[i] = '\xFF';
+ } else {
+ data[size - i - 1] = '\xFF';
+ }
+ }
+ }
+
+ /* Enable bit mode before writing, then disable it afterwards. */
+ EnableBitmode(mpsse, 1);
+ retval = Write(mpsse, data, size);
+ EnableBitmode(mpsse, 0);
+
+ return retval;
+}
+
+/*
+ * Send data out via the selected serial protocol.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @data - Buffer of data to send.
+ * @size - Size of data.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int Write(struct mpsse_context* mpsse, const void* vdata, int size) {
+ const uint8_t* data = vdata;
+ uint8_t* buf = NULL;
+ int retval = MPSSE_FAIL, buf_size = 0, txsize = 0, n = 0;
+
+ if (is_valid_context(mpsse)) {
+ if (mpsse->mode) {
+ while (n < size) {
+ txsize = size - n;
+ if (txsize > mpsse->xsize) {
+ txsize = mpsse->xsize;
+ }
+
+ /*
+ * For I2C we need to send each byte individually so that we can
+ * read back each individual ACK bit, so set the transmit size to 1.
+ */
+ if (mpsse->mode == I2C) {
+ txsize = 1;
+ }
+
+ buf = build_block_buffer(mpsse, mpsse->tx, data + n, txsize, &buf_size);
+ if (buf) {
+ retval = raw_write(mpsse, buf, buf_size);
+ n += txsize;
+ free(buf);
+
+ if (retval == MPSSE_FAIL) {
+ break;
+ }
+
+ /* Read in the ACK bit and store it in mpsse->rack */
+ if (mpsse->mode == I2C) {
+ raw_read(mpsse, (uint8_t*)&mpsse->rack, 1);
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (retval == MPSSE_OK && n == size) {
+ retval = MPSSE_OK;
+ }
+ }
+
+ return retval;
+}
+
+/* Performs a read. For internal use only; see Read() and ReadBits(). */
+static uint8_t* InternalRead(struct mpsse_context* mpsse, int size) {
+ uint8_t *data = NULL, *buf = NULL;
+ uint8_t sbuf[SPI_RW_SIZE] = {0};
+ int n = 0, rxsize = 0, data_size = 0, retval = 0;
+
+ if (is_valid_context(mpsse)) {
+ if (mpsse->mode) {
+ buf = malloc(size);
+ if (buf) {
+ memset(buf, 0, size);
+
+ while (n < size) {
+ rxsize = size - n;
+ if (rxsize > mpsse->xsize) {
+ rxsize = mpsse->xsize;
+ }
+
+ data = build_block_buffer(mpsse, mpsse->rx, sbuf, rxsize, &data_size);
+ if (data) {
+ retval = raw_write(mpsse, data, data_size);
+ free(data);
+
+ if (retval == MPSSE_OK) {
+ n += raw_read(mpsse, buf + n, rxsize);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return buf;
+}
+
+/*
+ * Reads data over the selected serial protocol.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @size - Number of bytes to read.
+ *
+ * Returns a pointer to the read data on success.
+ * Returns NULL on failure.
+ */
+#ifdef SWIGPYTHON
+swig_string_data Read(struct mpsse_context* mpsse, int size)
+#else
+uint8_t* Read(struct mpsse_context* mpsse, int size)
+#endif
+{
+ uint8_t* buf = NULL;
+
+ buf = InternalRead(mpsse, size);
+
+#ifdef SWIGPYTHON
+ swig_string_data sdata = {0};
+ sdata.size = size;
+ sdata.data = buf;
+ return sdata;
+#else
+ return buf;
+#endif
+}
+
+/*
+ * Performs a bit-wise read of up to 8 bits.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @size - Number of bits to read.
+ *
+ * Returns an 8-bit byte containing the read bits.
+ */
+char ReadBits(struct mpsse_context* mpsse, int size) {
+ char bits = 0;
+ uint8_t* rdata = NULL;
+
+ if (size > 8) {
+ size = 8;
+ }
+
+ EnableBitmode(mpsse, 1);
+ rdata = InternalRead(mpsse, size);
+ EnableBitmode(mpsse, 0);
+
+ if (rdata) {
+ /* The last byte in rdata will have all the read bits set or unset as
+ * needed. */
+ bits = rdata[size - 1];
+
+ if (mpsse->endianess == MSB) {
+ /*
+ * In MSB mode, bits are sifted in from the left. If less than 8 bits were
+ * read, we need to shift them left accordingly.
+ */
+ bits = bits << (8 - size);
+ } else if (mpsse->endianess == LSB) {
+ /*
+ * In LSB mode, bits are shifted in from the right. If less than 8 bits
+ * were
+ * read, we need to shift them right accordingly.
+ */
+ bits = bits >> (8 - size);
+ }
+
+ free(rdata);
+ }
+
+ return bits;
+}
+
+/*
+ * Reads and writes data over the selected serial protocol (SPI only).
+ *
+ * @mpsse - MPSSE context pointer.
+ * @data - Buffer containing bytes to write.
+ * @size - Number of bytes to transfer.
+ *
+ * Returns a pointer to the read data on success.
+ * Returns NULL on failure.
+ */
+#ifdef SWIGPYTHON
+swig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size)
+#else
+uint8_t* Transfer(struct mpsse_context* mpsse, uint8_t* data, int size)
+#endif
+{
+ uint8_t *txdata = NULL, *buf = NULL;
+ int n = 0, data_size = 0, rxsize = 0, retval = 0;
+
+ if (is_valid_context(mpsse)) {
+ /* Make sure we're configured for one of the SPI modes */
+ if (mpsse->mode >= SPI0 && mpsse->mode <= SPI3) {
+ buf = malloc(size);
+ if (buf) {
+ memset(buf, 0, size);
+
+ while (n < size) {
+ /* When sending and recieving, FTDI chips don't seem to like large
+ * data blocks. Limit the size of each block to SPI_TRANSFER_SIZE */
+ rxsize = size - n;
+ if (rxsize > SPI_TRANSFER_SIZE) {
+ rxsize = SPI_TRANSFER_SIZE;
+ }
+
+ txdata =
+ build_block_buffer(mpsse, mpsse->txrx, data + n,
+ rxsize, &data_size);
+ if (txdata) {
+ retval = raw_write(mpsse, txdata, data_size);
+ free(txdata);
+
+ if (retval == MPSSE_OK) {
+ n += raw_read(mpsse, (buf + n), rxsize);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+#ifdef SWIGPYTHON
+ swig_string_data sdata = {0};
+ sdata.size = n;
+ sdata.data = (char*)buf;
+ return sdata;
+#else
+ return buf;
+#endif
+}
+
+/*
+ * Returns the last received ACK bit.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns either an ACK (0) or a NACK (1).
+ */
+int GetAck(struct mpsse_context* mpsse) {
+ int ack = 0;
+
+ if (is_valid_context(mpsse)) {
+ ack = (mpsse->rack & 0x01);
+ }
+
+ return ack;
+}
+
+/*
+ * Sets the transmitted ACK bit.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @ack - 0 to send ACKs, 1 to send NACKs.
+ *
+ * Returns void.
+ */
+void SetAck(struct mpsse_context* mpsse, int ack) {
+ if (is_valid_context(mpsse)) {
+ if (ack == NACK) {
+ mpsse->tack = 0xFF;
+ } else {
+ mpsse->tack = 0x00;
+ }
+ }
+
+ return;
+}
+
+/*
+ * Causes libmpsse to send ACKs after each read byte in I2C mode.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns void.
+ */
+void SendAcks(struct mpsse_context* mpsse) {
+ return SetAck(mpsse, ACK);
+}
+
+/*
+ * Causes libmpsse to send NACKs after each read byte in I2C mode.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns void.
+ */
+void SendNacks(struct mpsse_context* mpsse) {
+ return SetAck(mpsse, NACK);
+}
+
+/*
+ * Send data stop condition.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int Stop(struct mpsse_context* mpsse) {
+ int retval = MPSSE_OK;
+
+ if (is_valid_context(mpsse)) {
+ /* In I2C mode, we need to ensure that the data line goes low while the
+ * clock line is low to avoid sending an inadvertent start condition */
+ if (mpsse->mode == I2C) {
+ retval |= set_bits_low(mpsse, (mpsse->pidle & ~DO & ~SK));
+ }
+
+ /* Send the stop condition */
+ retval |= set_bits_low(mpsse, mpsse->pstop);
+
+ if (retval == MPSSE_OK) {
+ /* Restore the pins to their idle states */
+ retval |= set_bits_low(mpsse, mpsse->pidle);
+ }
+
+ mpsse->status = STOPPED;
+ } else {
+ retval = MPSSE_FAIL;
+ mpsse->status = STOPPED;
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the specified pin high.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @pin - Pin number to set high.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int PinHigh(struct mpsse_context* mpsse, int pin) {
+ int retval = MPSSE_FAIL;
+
+ if (is_valid_context(mpsse)) {
+ retval = gpio_write(mpsse, pin, HIGH);
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the specified pin low.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @pin - Pin number to set low.
+ *
+ * Returns MPSSE_OK on success.
+ * Returns MPSSE_FAIL on failure.
+ */
+int PinLow(struct mpsse_context* mpsse, int pin) {
+ int retval = MPSSE_FAIL;
+
+ if (is_valid_context(mpsse)) {
+ retval = gpio_write(mpsse, pin, LOW);
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the input/output direction of all pins. For use in BITBANG mode only.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @direction - Byte indicating input/output direction of each bit. 1 is out.
+ *
+ * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise.
+ */
+int SetDirection(struct mpsse_context* mpsse, uint8_t direction) {
+ int retval = MPSSE_FAIL;
+
+ if (is_valid_context(mpsse)) {
+ if (mpsse->mode == BITBANG) {
+ if (ftdi_set_bitmode(&mpsse->ftdi, direction, BITMODE_BITBANG) == 0) {
+ retval = MPSSE_OK;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * Sets the input/output value of all pins. For use in BITBANG mode only.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @data - Byte indicating bit hi/low value of each bit.
+ *
+ * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise.
+ */
+int WritePins(struct mpsse_context* mpsse, uint8_t data) {
+ int retval = MPSSE_FAIL;
+
+ if (is_valid_context(mpsse)) {
+ if (mpsse->mode == BITBANG) {
+ if (ftdi_write_data(&mpsse->ftdi, &data, 1) == 0) {
+ retval = MPSSE_OK;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * Reads the state of the chip's pins. For use in BITBANG mode only.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns a byte with the corresponding pin's bits set to 1 or 0.
+ */
+int ReadPins(struct mpsse_context* mpsse) {
+ uint8_t val = 0;
+
+ if (is_valid_context(mpsse)) {
+ ftdi_read_pins((struct ftdi_context*)&mpsse->ftdi, (uint8_t*)&val);
+ }
+
+ return (int)val;
+}
+
+/*
+ * Checks if a specific pin is high or low. For use in BITBANG mode only.
+ *
+ * @mpsse - MPSSE context pointer.
+ * @pin - The pin number.
+ * @state - The state of the pins, as returned by ReadPins.
+ * If set to -1, ReadPins will automatically be called.
+ *
+ * Returns a 1 if the pin is high, 0 if the pin is low.
+ */
+int PinState(struct mpsse_context* mpsse, int pin, int state) {
+ if (state == -1) {
+ state = ReadPins(mpsse);
+ }
+
+ /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert
+ * these defines into an absolute pin number. */
+ if (mpsse->mode != BITBANG) {
+ pin += NUM_GPIOL_PINS;
+ }
+
+ return ((state & (1 << pin)) >> pin);
+}
+
+/*
+ * Places all I/O pins into a tristate mode.
+ *
+ * @mpsse - MPSSE context pointer.
+ *
+ * Returns MPSSE_OK on success, MPSSE_FAIL on failure.
+ */
+int Tristate(struct mpsse_context* mpsse) {
+ uint8_t cmd[CMD_SIZE] = {0};
+
+ /* Tristate the all I/O pins (FT232H only) */
+ cmd[0] = TRISTATE_IO;
+ cmd[1] = 0xFF;
+ cmd[2] = 0xFF;
+
+ return raw_write(mpsse, cmd, sizeof(cmd));
+}
diff --git a/trunks/ftdi/mpsse.h b/trunks/ftdi/mpsse.h
new file mode 100644
index 0000000..c0c3c9d
--- /dev/null
+++ b/trunks/ftdi/mpsse.h
@@ -0,0 +1,251 @@
+/*
+/*
+/*Copyright (C) 2015 The Android Open Source Project
+/*
+/*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.
+ */
+ *
+ * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
+ * f1a6744b), and modified to suite the Chromium OS project.
+ */
+
+#ifndef TRUNKS_FTDI_MPSSE_H_
+#define TRUNKS_FTDI_MPSSE_H_
+
+#include <libftdi1/ftdi.h>
+#include <stdint.h>
+
+#define MPSSE_OK 0
+#define MPSSE_FAIL -1
+
+#define MSB 0x00
+#define LSB 0x08
+
+#define CHUNK_SIZE 65535
+#define SPI_RW_SIZE (63 * 1024)
+#define SPI_TRANSFER_SIZE 512
+#define I2C_TRANSFER_SIZE 64
+
+#define LATENCY_MS 2
+#define TIMEOUT_DIVISOR 1000000
+#define USB_TIMEOUT 120000
+#define SETUP_DELAY 25000
+
+#define BITMODE_RESET 0
+#define BITMODE_MPSSE 2
+
+#define CMD_SIZE 3
+#define MAX_SETUP_COMMANDS 10
+#define SS_TX_COUNT 3
+
+#define LOW 0
+#define HIGH 1
+#define NUM_GPIOL_PINS 4
+#define NUM_GPIO_PINS 12
+
+#define NULL_CONTEXT_ERROR_MSG "NULL MPSSE context pointer!"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FTDI interfaces */
+enum interface {
+ IFACE_ANY = INTERFACE_ANY,
+ IFACE_A = INTERFACE_A,
+ IFACE_B = INTERFACE_B,
+ IFACE_C = INTERFACE_C,
+ IFACE_D = INTERFACE_D
+};
+
+/* Common clock rates */
+enum clock_rates {
+ ONE_HUNDRED_KHZ = 100000,
+ FOUR_HUNDRED_KHZ = 400000,
+ ONE_MHZ = 1000000,
+ TWO_MHZ = 2000000,
+ FIVE_MHZ = 5000000,
+ SIX_MHZ = 6000000,
+ TEN_MHZ = 10000000,
+ TWELVE_MHZ = 12000000,
+ FIFTEEN_MHZ = 15000000,
+ THIRTY_MHZ = 30000000,
+ SIXTY_MHZ = 60000000
+};
+
+/* Supported MPSSE modes */
+enum modes {
+ SPI0 = 1,
+ SPI1 = 2,
+ SPI2 = 3,
+ SPI3 = 4,
+ I2C = 5,
+ GPIO = 6,
+ BITBANG = 7,
+};
+
+enum pins {
+ SK = 1,
+ DO = 2,
+ DI = 4,
+ CS = 8,
+ GPIO0 = 16,
+ GPIO1 = 32,
+ GPIO2 = 64,
+ GPIO3 = 128
+};
+
+enum gpio_pins {
+ GPIOL0 = 0,
+ GPIOL1 = 1,
+ GPIOL2 = 2,
+ GPIOL3 = 3,
+ GPIOH0 = 4,
+ GPIOH1 = 5,
+ GPIOH2 = 6,
+ GPIOH3 = 7,
+ GPIOH4 = 8,
+ GPIOH5 = 9,
+ GPIOH6 = 10,
+ GPIOH7 = 11
+};
+
+enum i2c_ack { ACK = 0, NACK = 1 };
+
+/* SK/DO/CS and GPIOs are outputs, DI is an input */
+#define DEFAULT_TRIS (SK | DO | CS | GPIO0 | GPIO1 | GPIO2 | GPIO3)
+#define DEFAULT_PORT (SK | CS) /* SK and CS are high, all others low */
+
+enum mpsse_commands {
+ INVALID_COMMAND = 0xAB,
+ ENABLE_ADAPTIVE_CLOCK = 0x96,
+ DISABLE_ADAPTIVE_CLOCK = 0x97,
+ ENABLE_3_PHASE_CLOCK = 0x8C,
+ DISABLE_3_PHASE_CLOCK = 0x8D,
+ TCK_X5 = 0x8A,
+ TCK_D5 = 0x8B,
+ CLOCK_N_CYCLES = 0x8E,
+ CLOCK_N8_CYCLES = 0x8F,
+ PULSE_CLOCK_IO_HIGH = 0x94,
+ PULSE_CLOCK_IO_LOW = 0x95,
+ CLOCK_N8_CYCLES_IO_HIGH = 0x9C,
+ CLOCK_N8_CYCLES_IO_LOW = 0x9D,
+ TRISTATE_IO = 0x9E,
+};
+
+enum low_bits_status { STARTED, STOPPED };
+
+struct vid_pid {
+ int vid;
+ int pid;
+ char* description;
+};
+
+struct mpsse_context {
+ char* description;
+ struct ftdi_context ftdi;
+ enum modes mode;
+ enum low_bits_status status;
+ int flush_after_read;
+ int vid;
+ int pid;
+ int clock;
+ int xsize;
+ uint8_t endianess;
+ uint8_t opened;
+ uint8_t tris;
+ uint8_t pstart;
+ uint8_t pstop;
+ uint8_t pidle;
+ uint8_t gpioh;
+ uint8_t trish;
+ uint8_t bitbang;
+ uint8_t tx;
+ uint8_t rx;
+ uint8_t txrx;
+ uint8_t tack;
+ uint8_t rack;
+};
+
+struct mpsse_context* MPSSE(enum modes mode, int freq, int endianess);
+struct mpsse_context* Open(int vid,
+ int pid,
+ enum modes mode,
+ int freq,
+ int endianess,
+ int interface,
+ const char* description,
+ const char* serial);
+struct mpsse_context* OpenIndex(int vid,
+ int pid,
+ enum modes mode,
+ int freq,
+ int endianess,
+ int interface,
+ const char* description,
+ const char* serial,
+ int index);
+void Close(struct mpsse_context* mpsse);
+const char* ErrorString(struct mpsse_context* mpsse);
+int SetMode(struct mpsse_context* mpsse, int endianess);
+void EnableBitmode(struct mpsse_context* mpsse, int tf);
+int SetClock(struct mpsse_context* mpsse, uint32_t freq);
+int GetClock(struct mpsse_context* mpsse);
+int GetVid(struct mpsse_context* mpsse);
+int GetPid(struct mpsse_context* mpsse);
+const char* GetDescription(struct mpsse_context* mpsse);
+int SetLoopback(struct mpsse_context* mpsse, int enable);
+void SetCSIdle(struct mpsse_context* mpsse, int idle);
+int Start(struct mpsse_context* mpsse);
+int Write(struct mpsse_context* mpsse, const void* data, int size);
+int Stop(struct mpsse_context* mpsse);
+int GetAck(struct mpsse_context* mpsse);
+void SetAck(struct mpsse_context* mpsse, int ack);
+void SendAcks(struct mpsse_context* mpsse);
+void SendNacks(struct mpsse_context* mpsse);
+void FlushAfterRead(struct mpsse_context* mpsse, int tf);
+int PinHigh(struct mpsse_context* mpsse, int pin);
+int PinLow(struct mpsse_context* mpsse, int pin);
+int SetDirection(struct mpsse_context* mpsse, uint8_t direction);
+int WriteBits(struct mpsse_context* mpsse, char bits, size_t size);
+char ReadBits(struct mpsse_context* mpsse, int size);
+int WritePins(struct mpsse_context* mpsse, uint8_t data);
+int ReadPins(struct mpsse_context* mpsse);
+int PinState(struct mpsse_context* mpsse, int pin, int state);
+int Tristate(struct mpsse_context* mpsse);
+char Version(void);
+
+#ifdef SWIGPYTHON
+typedef struct swig_string_data {
+ int size;
+ char* data;
+} swig_string_data;
+
+swig_string_data Read(struct mpsse_context* mpsse, int size);
+swig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size);
+#else
+uint8_t* Read(struct mpsse_context* mpsse, int size);
+uint8_t* Transfer(struct mpsse_context* mpsse,
+ uint8_t* data, int size);
+
+int FastWrite(struct mpsse_context* mpsse, char* data, int size);
+int FastRead(struct mpsse_context* mpsse, char* data, int size);
+int FastTransfer(struct mpsse_context* mpsse,
+ char* wdata,
+ char* rdata,
+ int size);
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif /* TRUNKS_FTDI_MPSSE_H_ */
diff --git a/trunks/ftdi/support.c b/trunks/ftdi/support.c
new file mode 100644
index 0000000..9b7c05d
--- /dev/null
+++ b/trunks/ftdi/support.c
@@ -0,0 +1,277 @@
+/*
+/*
+/*Copyright (C) 2015 The Android Open Source Project
+/*
+/*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.
+ */
+ *
+ * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
+ * f1a6744b), and modified to suite the Chromium OS project.
+ *
+ * Internal functions used by libmpsse.
+ *
+ * Craig Heffner
+ * 27 December 2011
+ */
+
+#include <string.h>
+
+#include "trunks/ftdi/support.h"
+
+/* Write data to the FTDI chip */
+int raw_write(struct mpsse_context* mpsse, uint8_t* buf, int size) {
+ int retval = MPSSE_FAIL;
+
+ if (mpsse->mode) {
+ if (ftdi_write_data(&mpsse->ftdi, buf, size) == size) {
+ retval = MPSSE_OK;
+ }
+ }
+
+ return retval;
+}
+
+/* Read data from the FTDI chip */
+int raw_read(struct mpsse_context* mpsse, uint8_t* buf, int size) {
+ int n = 0, r = 0;
+
+ if (mpsse->mode) {
+ while (n < size) {
+ r = ftdi_read_data(&mpsse->ftdi, buf, size);
+ if (r < 0)
+ break;
+ n += r;
+ }
+
+ if (mpsse->flush_after_read) {
+ /*
+ * Make sure the buffers are cleared after a read or subsequent reads may
+ *fail.
+ *
+ * Is this needed anymore? It slows down repetitive read operations by
+ *~8%.
+ */
+ ftdi_usb_purge_rx_buffer(&mpsse->ftdi);
+ }
+ }
+
+ return n;
+}
+
+/* Sets the read and write timeout periods for bulk usb data transfers. */
+void set_timeouts(struct mpsse_context* mpsse, int timeout) {
+ if (mpsse->mode) {
+ mpsse->ftdi.usb_read_timeout = timeout;
+ mpsse->ftdi.usb_write_timeout = timeout;
+ }
+
+ return;
+}
+
+/* Convert a frequency to a clock divisor */
+uint16_t freq2div(uint32_t system_clock, uint32_t freq) {
+ return (((system_clock / freq) / 2) - 1);
+}
+
+/* Convert a clock divisor to a frequency */
+uint32_t div2freq(uint32_t system_clock, uint16_t div) {
+ return (system_clock / ((1 + div) * 2));
+}
+
+/* Builds a buffer of commands + data blocks */
+uint8_t* build_block_buffer(struct mpsse_context* mpsse,
+ uint8_t cmd,
+ const uint8_t* data,
+ int size,
+ int* buf_size) {
+ uint8_t* buf = NULL;
+ int i = 0, j = 0, k = 0, dsize = 0, num_blocks = 0, total_size = 0,
+ xfer_size = 0;
+ uint16_t rsize = 0;
+
+ *buf_size = 0;
+
+ /* Data block size is 1 in I2C, or when in bitmode */
+ if (mpsse->mode == I2C || (cmd & MPSSE_BITMODE)) {
+ xfer_size = 1;
+ } else {
+ xfer_size = mpsse->xsize;
+ }
+
+ num_blocks = (size / xfer_size);
+ if (size % xfer_size) {
+ num_blocks++;
+ }
+
+ /* The total size of the data will be the data size + the write command */
+ total_size = size + (CMD_SIZE * num_blocks);
+
+ /* In I2C we have to add 3 additional commands per data block */
+ if (mpsse->mode == I2C) {
+ total_size += (CMD_SIZE * 3 * num_blocks);
+ }
+
+ buf = malloc(total_size);
+ if (buf) {
+ memset(buf, 0, total_size);
+
+ for (j = 0; j < num_blocks; j++) {
+ dsize = size - k;
+ if (dsize > xfer_size) {
+ dsize = xfer_size;
+ }
+
+ /* The reported size of this block is block size - 1 */
+ rsize = dsize - 1;
+
+ /* For I2C we need to ensure that the clock pin is set low prior to
+ * clocking out data */
+ if (mpsse->mode == I2C) {
+ buf[i++] = SET_BITS_LOW;
+ buf[i++] = mpsse->pstart & ~SK;
+
+ /* On receive, we need to ensure that the data out line is set as an
+ * input to avoid contention on the bus */
+ if (cmd == mpsse->rx) {
+ buf[i++] = mpsse->tris & ~DO;
+ } else {
+ buf[i++] = mpsse->tris;
+ }
+ }
+
+ /* Copy in the command for this block */
+ buf[i++] = cmd;
+ buf[i++] = (rsize & 0xFF);
+ if (!(cmd & MPSSE_BITMODE)) {
+ buf[i++] = ((rsize >> 8) & 0xFF);
+ }
+
+ /* On a write, copy the data to transmit after the command */
+ if (cmd == mpsse->tx || cmd == mpsse->txrx) {
+ memcpy(buf + i, data + k, dsize);
+
+ /* i == offset into buf */
+ i += dsize;
+ /* k == offset into data */
+ k += dsize;
+ }
+
+ /* In I2C mode we need to clock one ACK bit after each byte */
+ if (mpsse->mode == I2C) {
+ /* If we are receiving data, then we need to clock out an ACK for each
+ * byte */
+ if (cmd == mpsse->rx) {
+ buf[i++] = SET_BITS_LOW;
+ buf[i++] = mpsse->pstart & ~SK;
+ buf[i++] = mpsse->tris;
+
+ buf[i++] = mpsse->tx | MPSSE_BITMODE;
+ buf[i++] = 0;
+ buf[i++] = mpsse->tack;
+ }
+ /* If we are sending data, then we need to clock in an ACK for each byte
+ */
+ else if (cmd == mpsse->tx) {
+ /* Need to make data out an input to avoid contention on the bus when
+ * the slave sends an ACK */
+ buf[i++] = SET_BITS_LOW;
+ buf[i++] = mpsse->pstart & ~SK;
+ buf[i++] = mpsse->tris & ~DO;
+
+ buf[i++] = mpsse->rx | MPSSE_BITMODE;
+ buf[i++] = 0;
+ buf[i++] = SEND_IMMEDIATE;
+ }
+ }
+ }
+
+ *buf_size = i;
+ }
+
+ return buf;
+}
+
+/* Set the low bit pins high/low */
+int set_bits_low(struct mpsse_context* mpsse, int port) {
+ char buf[CMD_SIZE] = {0};
+
+ buf[0] = SET_BITS_LOW;
+ buf[1] = port;
+ buf[2] = mpsse->tris;
+
+ return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf));
+}
+
+/* Set the high bit pins high/low */
+int set_bits_high(struct mpsse_context* mpsse, int port) {
+ char buf[CMD_SIZE] = {0};
+
+ buf[0] = SET_BITS_HIGH;
+ buf[1] = port;
+ buf[2] = mpsse->trish;
+
+ return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf));
+}
+
+/* Set the GPIO pins high/low */
+int gpio_write(struct mpsse_context* mpsse, int pin, int direction) {
+ int retval = MPSSE_FAIL;
+
+ if (mpsse->mode == BITBANG) {
+ if (direction == HIGH) {
+ mpsse->bitbang |= (1 << pin);
+ } else {
+ mpsse->bitbang &= ~(1 << pin);
+ }
+
+ if (set_bits_high(mpsse, mpsse->bitbang) == MPSSE_OK) {
+ retval = raw_write(mpsse, (uint8_t*)&mpsse->bitbang, 1);
+ }
+ } else {
+ /* The first four pins can't be changed unless we are in a stopped status */
+ if (pin < NUM_GPIOL_PINS && mpsse->status == STOPPED) {
+ /* Convert pin number (0-3) to the corresponding pin bit */
+ pin = (GPIO0 << pin);
+
+ if (direction == HIGH) {
+ mpsse->pstart |= pin;
+ mpsse->pidle |= pin;
+ mpsse->pstop |= pin;
+ } else {
+ mpsse->pstart &= ~pin;
+ mpsse->pidle &= ~pin;
+ mpsse->pstop &= ~pin;
+ }
+
+ retval = set_bits_low(mpsse, mpsse->pstop);
+ } else if (pin >= NUM_GPIOL_PINS && pin < NUM_GPIO_PINS) {
+ /* Convert pin number (4 - 11) to the corresponding pin bit */
+ pin -= NUM_GPIOL_PINS;
+
+ if (direction == HIGH) {
+ mpsse->gpioh |= (1 << pin);
+ } else {
+ mpsse->gpioh &= ~(1 << pin);
+ }
+
+ retval = set_bits_high(mpsse, mpsse->gpioh);
+ }
+ }
+
+ return retval;
+}
+
+/* Checks if a given MPSSE context is valid. */
+int is_valid_context(struct mpsse_context* mpsse) {
+ return mpsse != NULL;
+}
diff --git a/trunks/ftdi/support.h b/trunks/ftdi/support.h
new file mode 100644
index 0000000..b9455a9
--- /dev/null
+++ b/trunks/ftdi/support.h
@@ -0,0 +1,42 @@
+/*
+/*
+/*Copyright (C) 2015 The Android Open Source Project
+/*
+/*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.
+ */
+ *
+ * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
+ * f1a6744b), and modified to suite the Chromium OS project.
+ */
+
+#ifndef TRUNKS_FTDI_SUPPORT_H_
+#define TRUNKS_FTDI_SUPPORT_H_
+
+#include "trunks/ftdi/mpsse.h"
+
+int raw_write(struct mpsse_context* mpsse, uint8_t* buf, int size);
+int raw_read(struct mpsse_context* mpsse, uint8_t* buf, int size);
+void set_timeouts(struct mpsse_context* mpsse, int timeout);
+uint16_t freq2div(uint32_t system_clock, uint32_t freq);
+uint32_t div2freq(uint32_t system_clock, uint16_t div);
+uint8_t* build_block_buffer(struct mpsse_context* mpsse,
+ uint8_t cmd,
+ const uint8_t* data,
+ int size,
+ int* buf_size);
+int set_bits_high(struct mpsse_context* mpsse, int port);
+int set_bits_low(struct mpsse_context* mpsse, int port);
+int gpio_write(struct mpsse_context* mpsse, int pin, int direction);
+int is_valid_context(struct mpsse_context* mpsse);
+
+#endif /* TRUNKS_FTDI_SUPPORT_H_ */
diff --git a/trunks/generator/extract_commands.sh b/trunks/generator/extract_commands.sh
new file mode 100755
index 0000000..500747a
--- /dev/null
+++ b/trunks/generator/extract_commands.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+cat $1 |
+ # Mark descriptions and actions in the body.
+ sed 's/^[0-9. ]*Command and Response$/_COMMAND_SECTION/' |
+ sed 's/^[0-9. ]*Detailed Actions$/_ACTIONS_SECTION/' |
+ # Keep only command and response sections.
+ awk '/^_COMMAND_SECTION$/,/^_ACTIONS_SECTION$/ { print $0; }' |
+ sed 's/^_COMMAND_SECTION$//' |
+ sed 's/^_ACTIONS_SECTION$//' |
+ # Remove headers and footers.
+ sed 's/^.*Trusted Platform Module Library.*$//' |
+ sed 's/^.*Part 3: Commands.*$//' |
+ sed 's/^.*Family .2.0..*$//' |
+ sed 's/^.*Level 00 Revision.*$//' |
+ sed 's/^.*Published.*$//' |
+ sed 's/^.*Copyright.*$//' |
+ sed 's/^.*Page [0-9].*$//' |
+ sed 's/^.*October 31, 2013.*$//' |
+ # Remove table headers.
+ sed 's/^Type$//' | sed 's/^Name$//' | sed 's/^Description$//' |
+ # Remove leading spaces.
+ sed 's/^[ ][ ]*//' |
+ # Remove empty lines.
+ sed '/^$/d' |
+ # Mark begin and end.
+ awk '
+ BEGIN { print "_BEGIN"; }
+ { print $0; }
+ END { print "_END"; }
+ ' |
+ # Mark command / response tables.
+ sed 's/^Table [0-9]* . \(.*\) Command$/_INPUT_START \1/' |
+ sed 's/^Table [0-9]* . \(.*\) Response$/_OUTPUT_START \1/' |
+ # Mark argument types.
+ sed 's/^\(TPM[_A-Z0-9+]*\)$/_TYPE \1/' |
+ sed 's/^\(U*INT[0-9]*\)$/_TYPE \1/' |
+ # Filter out a few special cases that look like types but are not.
+ sed 's/^_TYPE TPM_ST_NO_SESSIONS$/TPM_ST_NO_SESSIONS/' |
+ sed 's/^_TYPE TPM_ALG_NULL$/TPM_ALG_NULL/' |
+ sed 's/^_TYPE TPM_CC_HMAC$/TPM_CC_HMAC/' |
+ sed 's/^_TYPE TPM_GENERATED_VALUE$/TPM_GENERATED_VALUE/' |
+ sed 's/^_TYPE \(TPM_RH_[A-Z+]*\)$/\1/' |
+ # Mark argument names.
+ awk '
+ BEGIN { last_line_was_type = 0; }
+ /^_.*$/ { print $0; }
+ /^_TYPE .*$/ { last_line_was_type = 1; }
+ /^[^_].*$/ { if (last_line_was_type) {
+ last_line_was_type = 0;
+ print "_NAME " $0;
+ if ($0 !~ /^[@a-zA-Z0-9]*$/) {
+ print "_ERROR: Invalid name."; } }
+ else { print $0; } }
+ ' |
+ # Consolidate comments to a single line and mark.
+ awk '
+ BEGIN { comment = ""; }
+ /^_.*$/ { if (comment != "") { print "_COMMENT " comment; comment = ""; }
+ print $0; }
+ /^[^_].*$/ { if (comment != "") { comment = comment " " $0; }
+ else { comment = $0 } }
+ ' |
+ # Fix typos.
+ sed 's/_COMMENT TPM_CC_PolicyNVWritten/_COMMENT TPM_CC_PolicyNvWritten/' |
+ # Strip off modifiers like TYPE+ and @name.
+ sed 's/^\(_TYPE .*\)[+]$/\1/' |
+ sed 's/^_NAME @\(.*\)$/_NAME \1/' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||CommandBlock*||End
+ # Begin:_BEGIN\n
+ # End:_END\n
+ # CommandBlock:InputTag||Argument*||OutputTag||Argument*
+ # InputTag:_INPUT_START <command>\n
+ # OutputTag:_OUTPUT_START <command>\n
+ # Argument:Type||Name[||Comment]
+ # Type:_TYPE <type>\n
+ # Name:_NAME <name>\n
+ # Comment:_COMMENT <comment>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN\n(_INPUT_START[^\n]*\n(_TYPE[^\n]*\n_NAME[^\n]*\n(_COMMENT[^\n]*\n)*)*_OUTPUT_START[^\n]*\n(_TYPE[^\n]*\n_NAME[^\n]*\n(_COMMENT[^\n]*\n)*)*)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+exit 0
diff --git a/trunks/generator/extract_structures.sh b/trunks/generator/extract_structures.sh
new file mode 100755
index 0000000..16ff2f6
--- /dev/null
+++ b/trunks/generator/extract_structures.sh
@@ -0,0 +1,392 @@
+#!/bin/sh
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+# Pull out types.
+cat $1 |
+ # Mark tables and section boundaries.
+ sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' |
+ sed 's/^Table [0-9]* . Definition of .*Types[^.]*$/_TYPES/' |
+ # Keep only table sections.
+ awk '/^_TYPES$/,/^_SECTION_BOUNDARY$/ { print $0; }' |
+ sed 's/^_TYPES$//' |
+ sed 's/^_SECTION_BOUNDARY$//' |
+ # Remove headers and footers.
+ sed 's/^.*Trusted Platform Module Library.*$//' |
+ sed 's/^.*Part 2: Structures.*$//' |
+ sed 's/^.*Family .2.0..*$//' |
+ sed 's/^.*Level 00 Revision.*$//' |
+ sed 's/^.*Published.*$//' |
+ sed 's/^.*Copyright.*$//' |
+ sed 's/^.*Page [0-9].*$//' |
+ sed 's/^.*October 31, 2013.*$//' |
+ # Remove table headers.
+ sed 's/^Type$//' | sed 's/^Name$//' | sed 's/^Description$//' |
+ # Remove leading spaces.
+ sed 's/^[ ][ ]*//' |
+ # Remove empty lines.
+ sed '/^$/d' |
+ # Mark begin and end and filter types.
+ awk '
+ BEGIN { print "_BEGIN_TYPES"; state = 0; }
+ /^[^ ]*$/ { if (!state) { print "_OLD_TYPE " $0; state = 1; }
+ else { print "_NEW_TYPE " $0; state = 0; } }
+ END { print "_END"; }
+ ' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||Typedef*||End
+ # Begin:_BEGIN_TYPES\n
+ # End:_END\n
+ # Typedef:OldType||NewType
+ # OldType:_OLD_TYPE <type>\n
+ # NewType:_NEW_TYPE <type>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_TYPES\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+# Pull out interface types.
+cat $1 |
+ awk '
+ BEGIN { print "_BEGIN_TYPES"; FS = "[ ()]+"; }
+ /^Table [0-9]* . Definition of \([A-Z_]*\) TPMI_.* Type[^.]*$/ {
+ print "_OLD_TYPE " $6;
+ print "_NEW_TYPE " $7; }
+ /^Table [0-9]* . Definition of \{.*\} \([A-Z_]*\) TPMI_.* Type[^.]*$/ {
+ print "_OLD_TYPE " $7;
+ print "_NEW_TYPE " $8; }
+ /^Table [0-9]* . Definition of \([A-Z_]*\) \{.*\} TPMI_.* Type[^.]*$/ {
+ print "_OLD_TYPE " $6;
+ print "_NEW_TYPE " $8; }
+ END { print "_END"; }
+ ' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||Typedef*||End
+ # Begin:_BEGIN_TYPES\n
+ # End:_END\n
+ # Typedef:OldType||NewType
+ # OldType:_OLD_TYPE <type>\n
+ # NewType:_NEW_TYPE <type>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_TYPES\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+# Pull out attribute types.
+cat $1 |
+ awk '
+ BEGIN { print "_BEGIN_TYPES"; FS = "[ ()]+"; }
+ /^Table [0-9]* . Definition of \([A-Z_0-9]*\) TPM[A-Z_]* Bits[^.]*$/ {
+ print "_OLD_TYPE " $6;
+ print "_NEW_TYPE " $7; }
+ END { print "_END"; }
+ ' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||Typedef*||End
+ # Begin:_BEGIN_TYPES\n
+ # End:_END\n
+ # Typedef:OldType||NewType
+ # OldType:_OLD_TYPE <type>\n
+ # NewType:_NEW_TYPE <type>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_TYPES\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+# Pull out constant values.
+cat $1 |
+ # Mark tables and section boundaries.
+ sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' |
+ sed 's/^Table [0-9]* . Definition of \(.*\) Constants[^.]*$/_CONSTANTS \1/' |
+ # Keep only table sections.
+ awk '/^_CONSTANTS .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' |
+ sed 's/^_SECTION_BOUNDARY$//' |
+ # Remove headers and footers.
+ sed 's/^.*Trusted Platform Module Library.*$//' |
+ sed 's/^.*Part 2: Structures.*$//' |
+ sed 's/^.*Family .2.0..*$//' |
+ sed 's/^.*Level 00 Revision.*$//' |
+ sed 's/^.*Published.*$//' |
+ sed 's/^.*Copyright.*$//' |
+ sed 's/^.*Page [0-9].*$//' |
+ sed 's/^.*October 31, 2013.*$//' |
+ # Remove table headers.
+ sed 's/^Name$//' | sed 's/^Value$//' | sed 's/^Comments$//' |
+ # Remove leading spaces.
+ sed 's/^[ ][ ]*//' |
+ # Remove empty lines.
+ sed '/^$/d' |
+ # Mark begin and end.
+ awk '
+ BEGIN { print "_BEGIN_CONSTANTS"; }
+ { print $0; }
+ END { print "_END"; }
+ ' |
+ # Mark type.
+ awk '
+ BEGIN { FS = "[ ()]+"; }
+ { print $0; }
+ /^_CONSTANTS \(\w*\) .*$/ { print "_TYPE " $2; }
+ ' |
+ # Mark names.
+ sed 's/^\(TPM_[_A-Z0-9a]*\)$/_NAME \1/' |
+ sed 's/^\(TPM_CC_[_A-Z0-9a-z]*\)$/_NAME \1/' |
+ sed 's/^\(RC_[_A-Z0-9]*\)$/_NAME \1/' |
+ sed 's/^\(PT_[_A-Z0-9]*\)$/_NAME \1/' |
+ sed 's/^\(HR_[_A-Z0-9]*\)$/_NAME \1/' |
+ sed 's/^\([_A-Z0-9]*FIRST\)$/_NAME \1/' |
+ sed 's/^\([_A-Z0-9]*LAST\)$/_NAME \1/' |
+ sed 's/^\(PLATFORM_PERSISTENT\)$/_NAME \1/' |
+ # Mark values and throw away everything else.
+ awk '
+ BEGIN { last_line_was_name = 0; }
+ /^_.*$/ { if ($0 !~ /^_NAME .*$/) { print $0; } }
+ /^_NAME .*$/ { if (last_line_was_name) {
+ last_line_was_name = 0;
+ if ($0 !~ /[A-Z_0-9x +]*/) { print "_ERROR: Invalid value"; }
+ print "_VALUE " $2; }
+ else { last_line_was_name = 1; print $0; } }
+ /^[^_].*$/ { if (last_line_was_name) {
+ last_line_was_name = 0;
+ if ($0 !~ /[A-Z_0-9x +]*/) { print "_ERROR: Invalid value"; }
+ print "_VALUE " $0; } }
+ ' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||TableBlock*||End
+ # Begin:_BEGIN_CONSTANTS\n
+ # End:_END\n
+ # TableBlock:TableTag||Type||Constant*
+ # TableTag:_CONSTANTS <name>\n
+ # Constant:Name||Value
+ # Type:_TYPE <type>\n
+ # Name:_NAME <name>\n
+ # Value:_VALUE <value>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_CONSTANTS\n(_CONSTANTS[^\n]*\n_TYPE[^\n]*\n(_NAME[^\n]*\n_VALUE[^\n]*\n)*)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+# Pull out structures.
+cat $1 |
+ # Mark tables and section boundaries.
+ sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' |
+ sed 's/^Table [0-9]* . Definition of \(.*\) Structure[^.]*$/_STRUCTURE \1/' |
+ # Keep only table sections.
+ awk '/^_STRUCTURE .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' |
+ sed 's/^_SECTION_BOUNDARY$//' |
+ # Remove headers and footers.
+ sed 's/^.*Trusted Platform Module Library.*$//' |
+ sed 's/^.*Part 2: Structures.*$//' |
+ sed 's/^.*Family .2.0..*$//' |
+ sed 's/^.*Level 00 Revision.*$//' |
+ sed 's/^.*Published.*$//' |
+ sed 's/^.*Copyright.*$//' |
+ sed 's/^.*Page [0-9].*$//' |
+ sed 's/^.*October 31, 2013.*$//' |
+ # Remove table headers.
+ sed 's/^Parameter$//' | sed 's/^Type$//' | sed 's/^Description$//' |
+ # Remove leading spaces.
+ sed 's/^[ ][ ]*//' |
+ # Remove empty lines.
+ sed '/^$/d' |
+ # Mark begin and end.
+ awk '
+ BEGIN { print "_BEGIN_STRUCTURES"; }
+ { print $0; }
+ END { print "_END"; }
+ ' |
+ # Mark field types.
+ sed 's/^\(+*TPM[_A-Z0-9+]*\)$/_TYPE \1/' |
+ sed 's/^\(UINT[0-9]*\)$/_TYPE \1/' |
+ sed 's/^\(BYTE*\)$/_TYPE \1/' |
+ # Mark field names and throw away everything else.
+ awk '
+ BEGIN { last_line = ""; }
+ /^_.*$/ { print $0; }
+ /^_TYPE .*$/ { if (last_line != "") { print "_NAME " last_line; }
+ else { print "_ERROR: Type with no name"; }
+ last_line = ""; }
+ /^[^_].*$/ { last_line = $0; }
+ ' |
+ # Change 'value [size] {:max}' to 'value[max]'.
+ sed 's/^\(_NAME \w*\).*\[\w*\].*[{][:] *\([a-zA-Z0-9_()/]*\)[}]$/\1[\2]/' |
+ # Strip off other modifiers.
+ sed 's/^\(_NAME \w*\)[ {].*/\1/' |
+ sed 's/^_TYPE +\(.*\)$/_TYPE \1/' |
+ sed 's/^_TYPE \(.*\)+$/_TYPE \1/' |
+ sed 's/^_NAME \/*\[.*\] *\(.*\)$/_NAME \1/' |
+ sed 's/^\(_NAME \w*\)=/\1/' |
+ sed 's/^_STRUCTURE \((.*) \)*{.*} \(.*\)/_STRUCTURE \2/' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||TableBlock*||End
+ # Begin:_BEGIN_STRUCTURES\n
+ # End:_END\n
+ # TableBlock:TableTag||Field*
+ # TableTag:_STRUCTURE <name>\n
+ # Field:Type||Name
+ # Type:_TYPE <type>\n
+ # Name:_NAME <name>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_STRUCTURES\n(_STRUCTURE[^\n]*\n(_TYPE[^\n]*\n_NAME[^\n]*\n)*)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+# Pull out unions.
+cat $1 |
+ # Mark tables and section boundaries.
+ sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' |
+ sed 's/^Table [0-9]* . Definition of \(.*\) Union[^.]*$/_UNION \1/' |
+ # Keep only table sections.
+ awk '/^_UNION .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' |
+ sed 's/^_SECTION_BOUNDARY$//' |
+ # Remove headers and footers.
+ sed 's/^.*Trusted Platform Module Library.*$//' |
+ sed 's/^.*Part 2: Structures.*$//' |
+ sed 's/^.*Family .2.0..*$//' |
+ sed 's/^.*Level 00 Revision.*$//' |
+ sed 's/^.*Published.*$//' |
+ sed 's/^.*Copyright.*$//' |
+ sed 's/^.*Page [0-9].*$//' |
+ sed 's/^.*October 31, 2013.*$//' |
+ # Remove table headers.
+ sed 's/^Parameter$//' | sed 's/^Type$//' | sed 's/^Selector$//' |
+ sed 's/^Description$//' |
+ # Remove leading spaces.
+ sed 's/^[ ][ ]*//' |
+ # Remove empty lines.
+ sed '/^$/d' |
+ # Mark begin and end.
+ awk '
+ BEGIN { print "_BEGIN_UNIONS"; }
+ { print $0; }
+ END { print "_END"; }
+ ' |
+ # Mark field types.
+ sed 's/^\(+*TPM[_A-Z0-9+a]*\)$/_TYPE \1/' |
+ sed 's/^\(UINT[0-9]*\)$/_TYPE \1/' |
+ sed 's/^\(BYTE*\)$/_TYPE \1/' |
+ # Mark field names and throw away everything else.
+ awk '
+ BEGIN { last_line = ""; }
+ /^_.*$/ { if ($0 !~ /^_TYPE .*$/) { last_line = ""; print $0; } }
+ /^_TYPE .*$/ { if (last_line !~ /^_TYPE .*$/) {
+ if (last_line != "" &&
+ last_line != "null" &&
+ last_line != "NOTE") {
+ print $0;
+ print "_NAME " last_line; }
+ else if (last_line == "") {
+ print "_ERROR: Type with no name"; }
+ last_line = $0; } }
+ /^[^_].*$/ { last_line = $0; }
+ ' |
+ # Change 'value [size] {:max}' to 'value[max]'.
+ sed 's/^\(_NAME \w*\).*\[\w*\].*[{][:] *\([a-zA-Z0-9_()/]*\)[}]$/\1[\2]/' |
+ # Strip off other modifiers.
+ sed 's/^\(_NAME \w*\) \(\[.*\]\)/\1\2/' |
+ sed 's/^\(_NAME \w*\)\( {|{\).*/\1/' |
+ sed 's/^_TYPE +\(.*\)$/_TYPE \1/' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||TableBlock*||End
+ # Begin:_BEGIN_UNIONS\n
+ # End:_END\n
+ # TableBlock:TableTag||Field*
+ # TableTag:_UNION <name>\n
+ # Field:Type||Name
+ # Type:_TYPE <type>\n
+ # Name:_NAME <name>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_UNIONS\n(_UNION[^\n]*\n(_TYPE[^\n]*\n_NAME[^\n]*\n)*)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+# Pull out default defines.
+cat $1 |
+ sed 's/^[A-Z]\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' |
+ sed 's/^Table [0-9]* . Defines for \([^.]*\)$/_DEFINES \1/' |
+ sed 's/^_DEFINES Implemented Commands$//' |
+ sed 's/^_DEFINES Implemented Algorithms$//' |
+ awk '/^_DEFINES .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' |
+ sed 's/^_SECTION_BOUNDARY$//' |
+ # Remove headers and footers.
+ sed 's/^.*Trusted Platform Module Library.*$//' |
+ sed 's/^.*Part 2: Structures.*$//' |
+ sed 's/^.*Family .2.0..*$//' |
+ sed 's/^.*Level 00 Revision.*$//' |
+ sed 's/^.*Published.*$//' |
+ sed 's/^.*Copyright.*$//' |
+ sed 's/^.*Page [0-9].*$//' |
+ sed 's/^.*October 31, 2013.*$//' |
+ # Remove table headers.
+ sed 's/^Name$//' | sed 's/^Value$//' | sed 's/^Description$//' |
+ # Remove most comments.
+ sed 's/^.*[g-wyz?]\+.*$//' |
+ # Remove leading spaces.
+ sed 's/^[ ][ ]*//' |
+ # Remove empty lines.
+ sed '/^$/d' |
+ # Mark begin and end.
+ awk '
+ BEGIN { print "_BEGIN_DEFINES"; }
+ { print $0; }
+ END { print "_END"; }
+ ' |
+ # Mark define names.
+ sed 's/^\([A-Z][_A-Z0-9]*\)$/_NAME \1/' |
+ sed 's/^_NAME NOTE$//' |
+ # Mark values and throw away everything else.
+ awk '
+ BEGIN { last_line_was_name = 0; }
+ /^_.*$/ { if ($0 !~ /^_NAME .*$/) { print $0; } }
+ /^_NAME .*$/ { if (last_line_was_name) {
+ last_line_was_name = 0;
+ if ($0 !~ /[A-Z_0-9x +()]*/) {
+ print "_ERROR: Invalid value"; }
+ print "_VALUE " $2; }
+ else { last_line_was_name = 1; print $0; } }
+ /^[^_].*$/ { if (last_line_was_name) {
+ last_line_was_name = 0;
+ if ($0 !~ /[A-Z_0-9x +()]*/) {
+ print "_ERROR: Invalid value"; }
+ print "_VALUE " $0; } }
+ ' |
+ # Sanity check. The format should now follow this grammar:
+ # Format:Begin||Define*||End
+ # Begin:_BEGIN_DEFINES\n
+ # End:_END\n
+ # Define:Name||Value
+ # Name:_NAME <name>\n
+ # Value:_VALUE <value>\n
+ awk '
+ BEGIN { RS = ""; }
+ $0 !~ /_BEGIN_DEFINES\n(_NAME[^\n]*\n_VALUE[^\n]*\n)*_END/ {
+ print "_ERROR: Format check failed."; }
+ { print $0; }
+ '
+
+exit 0
diff --git a/trunks/generator/generator.py b/trunks/generator/generator.py
new file mode 100755
index 0000000..09b6cd2
--- /dev/null
+++ b/trunks/generator/generator.py
@@ -0,0 +1,2092 @@
+#!/usr/bin/python2
+
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+"""A code generator for TPM 2.0 structures and commands.
+
+The generator takes as input a structures file as emitted by the
+extract_structures.sh script and a commands file as emitted by the
+extract_commands.sh script. It outputs valid C++ into tpm_generated.{h,cc}.
+
+The input grammar is documented in the extract_* scripts. Sample input for
+structures looks like this:
+_BEGIN_TYPES
+_OLD_TYPE UINT32
+_NEW_TYPE TPM_HANDLE
+_END
+_BEGIN_CONSTANTS
+_CONSTANTS (UINT32) TPM_SPEC
+_TYPE UINT32
+_NAME TPM_SPEC_FAMILY
+_VALUE 0x322E3000
+_NAME TPM_SPEC_LEVEL
+_VALUE 00
+_END
+_BEGIN_STRUCTURES
+_STRUCTURE TPMS_TIME_INFO
+_TYPE UINT64
+_NAME time
+_TYPE TPMS_CLOCK_INFO
+_NAME clockInfo
+_END
+
+Sample input for commands looks like this:
+_BEGIN
+_INPUT_START TPM2_Startup
+_TYPE TPMI_ST_COMMAND_TAG
+_NAME tag
+_COMMENT TPM_ST_NO_SESSIONS
+_TYPE UINT32
+_NAME commandSize
+_TYPE TPM_CC
+_NAME commandCode
+_COMMENT TPM_CC_Startup {NV}
+_TYPE TPM_SU
+_NAME startupType
+_COMMENT TPM_SU_CLEAR or TPM_SU_STATE
+_OUTPUT_START TPM2_Startup
+_TYPE TPM_ST
+_NAME tag
+_COMMENT see clause 8
+_TYPE UINT32
+_NAME responseSize
+_TYPE TPM_RC
+_NAME responseCode
+_END
+"""
+
+from __future__ import print_function
+
+import argparse
+import re
+
+import union_selectors
+
+_BASIC_TYPES = ['uint8_t', 'int8_t', 'int', 'uint16_t', 'int16_t',
+ 'uint32_t', 'int32_t', 'uint64_t', 'int64_t']
+_OUTPUT_FILE_H = 'tpm_generated.h'
+_OUTPUT_FILE_CC = 'tpm_generated.cc'
+_COPYRIGHT_HEADER = (
+ '// \n'
+ '// Copyright (C) 2015 The Android Open Source Project \n'
+ '// \n'
+ '// Licensed under the Apache License, Version 2.0 (the "License"); \n'
+ '// you may not use this file except in compliance with the License. \n'
+ '// \n'
+ '// http://www.apache.org/licenses/LICENSE-2.0 \n'
+ '// \n'
+ '// Unless required by applicable law or agreed to in writing, software \n'
+ '// distributed under the License is distributed on an "AS IS" BASIS, \n'
+ '// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or '
+ 'implied. \n'
+ '// See the License for the specific language governing permissions and \n'
+ '// limitations under the License. \n'
+ '// \n'
+ '// THIS CODE IS GENERATED - DO NOT MODIFY!\n')
+_HEADER_FILE_GUARD_HEADER = """
+#ifndef %(name)s
+#define %(name)s
+"""
+_HEADER_FILE_GUARD_FOOTER = """
+#endif // %(name)s
+"""
+_HEADER_FILE_INCLUDES = """
+#include <string>
+
+#include <base/basictypes.h>
+#include <base/callback_forward.h>
+
+#include "trunks/trunks_export.h"
+"""
+_IMPLEMENTATION_FILE_INCLUDES = """
+#include <string>
+
+#include <base/basictypes.h>
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/logging.h>
+#include <base/stl_util.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/sys_byteorder.h>
+#include <crypto/secure_hash.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/command_transceiver.h"
+#include "trunks/error_codes.h"
+
+"""
+_LOCAL_INCLUDE = """
+#include "trunks/%(filename)s"
+"""
+_NAMESPACE_BEGIN = """
+namespace trunks {
+"""
+_NAMESPACE_END = """
+} // namespace trunks
+"""
+_FORWARD_DECLARATIONS = """
+class AuthorizationDelegate;
+class CommandTransceiver;
+"""
+_FUNCTION_DECLARATIONS = """
+TRUNKS_EXPORT size_t GetNumberOfRequestHandles(TPM_CC command_code);
+TRUNKS_EXPORT size_t GetNumberOfResponseHandles(TPM_CC command_code);
+"""
+_CLASS_BEGIN = """
+class TRUNKS_EXPORT Tpm {
+ public:
+ // Does not take ownership of |transceiver|.
+ explicit Tpm(CommandTransceiver* transceiver) : transceiver_(transceiver) {}
+ virtual ~Tpm() {}
+
+"""
+_CLASS_END = """
+ private:
+ CommandTransceiver* transceiver_;
+
+ DISALLOW_COPY_AND_ASSIGN(Tpm);
+};
+"""
+_SERIALIZE_BASIC_TYPE = """
+TPM_RC Serialize_%(type)s(const %(type)s& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ %(type)s value_net = value;
+ switch (sizeof(%(type)s)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(%(type)s));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_%(type)s(
+ std::string* buffer,
+ %(type)s* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(%(type)s))
+ return TPM_RC_INSUFFICIENT;
+ %(type)s value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(%(type)s));
+ switch (sizeof(%(type)s)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(%(type)s)));
+ }
+ buffer->erase(0, sizeof(%(type)s));
+ return TPM_RC_SUCCESS;
+}
+"""
+_SERIALIZE_DECLARATION = """
+TRUNKS_EXPORT TPM_RC Serialize_%(type)s(
+ const %(type)s& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_%(type)s(
+ std::string* buffer,
+ %(type)s* value,
+ std::string* value_bytes);
+"""
+
+_SIMPLE_TPM2B_HELPERS_DECLARATION = """
+TRUNKS_EXPORT %(type)s Make_%(type)s(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_%(type)s(
+ const %(type)s& tpm2b);
+"""
+_COMPLEX_TPM2B_HELPERS_DECLARATION = """
+TRUNKS_EXPORT %(type)s Make_%(type)s(
+ const %(inner_type)s& inner);
+"""
+
+_HANDLE_COUNT_FUNCTION_START = """
+size_t GetNumberOf%(handle_type)sHandles(TPM_CC command_code) {
+ switch (command_code) {"""
+_HANDLE_COUNT_FUNCTION_CASE = """
+ case %(command_code)s: return %(handle_count)s;"""
+_HANDLE_COUNT_FUNCTION_END = """
+ default: LOG(WARNING) << "Unknown command code: " << command_code;
+ }
+ return 0;
+}
+"""
+
+def FixName(name):
+ """Fixes names to conform to Chromium style."""
+ # Handle names with array notation. E.g. 'myVar[10]' is grouped as 'myVar' and
+ # '[10]'.
+ match = re.search(r'([^\[]*)(\[.*\])*', name)
+ # Transform the name to Chromium style. E.g. 'myVarAgain' becomes
+ # 'my_var_again'.
+ fixed_name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', match.group(1)).lower()
+ return fixed_name + match.group(2) if match.group(2) else fixed_name
+
+
+def IsTPM2B(name):
+ return name.startswith('TPM2B_')
+
+
+def GetCppBool(condition):
+ if condition:
+ return 'true'
+ return 'false'
+
+
+class Typedef(object):
+ """Represents a TPM typedef.
+
+ Attributes:
+ old_type: The existing type in a typedef statement.
+ new_type: The new type in a typedef statement.
+ """
+
+ _TYPEDEF = 'typedef %(old_type)s %(new_type)s;\n'
+ _SERIALIZE_FUNCTION = """
+TPM_RC Serialize_%(new)s(
+ const %(new)s& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_%(old)s(value, buffer);
+}
+"""
+ _PARSE_FUNCTION = """
+TPM_RC Parse_%(new)s(
+ std::string* buffer,
+ %(new)s* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_%(old)s(buffer, value, value_bytes);
+}
+"""
+
+ def __init__(self, old_type, new_type):
+ """Initializes a Typedef instance.
+
+ Args:
+ old_type: The existing type in a typedef statement.
+ new_type: The new type in a typedef statement.
+ """
+ self.old_type = old_type
+ self.new_type = new_type
+
+ def OutputForward(self, out_file, defined_types, typemap):
+ """Writes a typedef definition to |out_file|.
+
+ Any outstanding dependencies will be forward declared. This method is the
+ same as Output() because forward declarations do not apply for typedefs.
+
+ Args:
+ out_file: The output file.
+ defined_types: A set of types for which definitions have already been
+ generated.
+ typemap: A dict mapping type names to the corresponding object.
+ """
+ self.Output(out_file, defined_types, typemap)
+
+ def Output(self, out_file, defined_types, typemap):
+ """Writes a typedef definition to |out_file|.
+
+ Any outstanding dependencies will be forward declared.
+
+ Args:
+ out_file: The output file.
+ defined_types: A set of types for which definitions have already been
+ generated.
+ typemap: A dict mapping type names to the corresponding object.
+ """
+ if self.new_type in defined_types:
+ return
+ # Make sure the dependency is already defined.
+ if self.old_type not in defined_types:
+ typemap[self.old_type].OutputForward(out_file, defined_types, typemap)
+ out_file.write(self._TYPEDEF % {'old_type': self.old_type,
+ 'new_type': self.new_type})
+ defined_types.add(self.new_type)
+
+ def OutputSerialize(self, out_file, serialized_types, typemap):
+ """Writes a serialize and parse function for the typedef to |out_file|.
+
+ Args:
+ out_file: The output file.
+ serialized_types: A set of types for which serialize and parse functions
+ have already been generated.
+ typemap: A dict mapping type names to the corresponding object.
+ """
+ if self.new_type in serialized_types:
+ return
+ if self.old_type not in serialized_types:
+ typemap[self.old_type].OutputSerialize(out_file, serialized_types,
+ typemap)
+ out_file.write(self._SERIALIZE_FUNCTION % {'old': self.old_type,
+ 'new': self.new_type})
+ out_file.write(self._PARSE_FUNCTION % {'old': self.old_type,
+ 'new': self.new_type})
+ serialized_types.add(self.new_type)
+
+
+class Constant(object):
+ """Represents a TPM constant.
+
+ Attributes:
+ const_type: The type of the constant (e.g. 'int').
+ name: The name of the constant (e.g. 'kMyConstant').
+ value: The value of the constant (e.g. '7').
+ """
+
+ _CONSTANT = 'const %(type)s %(name)s = %(value)s;\n'
+
+ def __init__(self, const_type, name, value):
+ """Initializes a Constant instance.
+
+ Args:
+ const_type: The type of the constant (e.g. 'int').
+ name: The name of the constant (e.g. 'kMyConstant').
+ value: The value of the constant (e.g. '7').
+ """
+ self.const_type = const_type
+ self.name = name
+ self.value = value
+
+ def Output(self, out_file, defined_types, typemap):
+ """Writes a constant definition to |out_file|.
+
+ Any outstanding dependencies will be forward declared.
+
+ Args:
+ out_file: The output file.
+ defined_types: A set of types for which definitions have already been
+ generated.
+ typemap: A dict mapping type names to the corresponding object.
+ """
+ # Make sure the dependency is already defined.
+ if self.const_type not in defined_types:
+ typemap[self.const_type].OutputForward(out_file, defined_types, typemap)
+ out_file.write(self._CONSTANT % {'type': self.const_type,
+ 'name': self.name,
+ 'value': self.value})
+
+
+class Structure(object):
+ """Represents a TPM structure or union.
+
+ Attributes:
+ name: The name of the structure.
+ is_union: A boolean indicating whether this is a union.
+ fields: A list of (type, name) tuples representing the struct fields.
+ depends_on: A list of strings for types this struct depends on other than
+ field types. See AddDependency() for more details.
+ """
+
+ _STRUCTURE = 'struct %(name)s {\n'
+ _STRUCTURE_FORWARD = 'struct %(name)s;\n'
+ _UNION = 'union %(name)s {\n'
+ _UNION_FORWARD = 'union %(name)s;\n'
+ _STRUCTURE_END = '};\n\n'
+ _STRUCTURE_FIELD = ' %(type)s %(name)s;\n'
+ _SERIALIZE_FUNCTION_START = """
+TPM_RC Serialize_%(type)s(
+ const %(type)s& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+"""
+ _SERIALIZE_FIELD = """
+ result = Serialize_%(type)s(value.%(name)s, buffer);
+ if (result) {
+ return result;
+ }
+"""
+ _SERIALIZE_FIELD_ARRAY = """
+ if (arraysize(value.%(name)s) < value.%(count)s) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.%(count)s; ++i) {
+ result = Serialize_%(type)s(value.%(name)s[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+"""
+ _SERIALIZE_FIELD_WITH_SELECTOR = """
+ result = Serialize_%(type)s(
+ value.%(name)s,
+ value.%(selector_name)s,
+ buffer);
+ if (result) {
+ return result;
+ }
+"""
+ _SERIALIZE_COMPLEX_TPM2B = """
+ std::string field_bytes;
+ result = Serialize_%(type)s(value.%(name)s, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+"""
+ _PARSE_FUNCTION_START = """
+TPM_RC Parse_%(type)s(
+ std::string* buffer,
+ %(type)s* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+"""
+ _PARSE_FIELD = """
+ result = Parse_%(type)s(
+ buffer,
+ &value->%(name)s,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+"""
+ _PARSE_FIELD_ARRAY = """
+ if (arraysize(value->%(name)s) < value->%(count)s) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->%(count)s; ++i) {
+ result = Parse_%(type)s(
+ buffer,
+ &value->%(name)s[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+"""
+ _PARSE_FIELD_WITH_SELECTOR = """
+ result = Parse_%(type)s(
+ buffer,
+ value->%(selector_name)s,
+ &value->%(name)s,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+"""
+ _SERIALIZE_FUNCTION_END = ' return result;\n}\n'
+ _ARRAY_FIELD_RE = re.compile(r'(.*)\[(.*)\]')
+ _ARRAY_FIELD_SIZE_RE = re.compile(r'^(count|size)')
+ _UNION_TYPE_RE = re.compile(r'^TPMU_.*')
+ _SERIALIZE_UNION_FUNCTION_START = """
+TPM_RC Serialize_%(union_type)s(
+ const %(union_type)s& value,
+ %(selector_type)s selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+"""
+ _SERIALIZE_UNION_FIELD = """
+ if (selector == %(selector_value)s) {
+ result = Serialize_%(field_type)s(value.%(field_name)s, buffer);
+ if (result) {
+ return result;
+ }
+ }
+"""
+ _SERIALIZE_UNION_FIELD_ARRAY = """
+ if (selector == %(selector_value)s) {
+ if (arraysize(value.%(field_name)s) < %(count)s) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < %(count)s; ++i) {
+ result = Serialize_%(field_type)s(value.%(field_name)s[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ }
+"""
+ _PARSE_UNION_FUNCTION_START = """
+TPM_RC Parse_%(union_type)s(
+ std::string* buffer,
+ %(selector_type)s selector,
+ %(union_type)s* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+"""
+ _PARSE_UNION_FIELD = """
+ if (selector == %(selector_value)s) {
+ result = Parse_%(field_type)s(
+ buffer,
+ &value->%(field_name)s,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+"""
+ _PARSE_UNION_FIELD_ARRAY = """
+ if (selector == %(selector_value)s) {
+ if (arraysize(value->%(field_name)s) < %(count)s) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < %(count)s; ++i) {
+ result = Parse_%(field_type)s(
+ buffer,
+ &value->%(field_name)s[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ }
+"""
+ _EMPTY_UNION_CASE = """
+ if (selector == %(selector_value)s) {
+ // Do nothing.
+ }
+"""
+ _SIMPLE_TPM2B_HELPERS = """
+%(type)s Make_%(type)s(
+ const std::string& bytes) {
+ %(type)s tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.%(buffer_name)s));
+ memset(&tpm2b, 0, sizeof(%(type)s));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.%(buffer_name)s, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_%(type)s(
+ const %(type)s& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.%(buffer_name)s);
+ return std::string(char_buffer, tpm2b.size);
+}
+"""
+ _COMPLEX_TPM2B_HELPERS = """
+%(type)s Make_%(type)s(
+ const %(inner_type)s& inner) {
+ %(type)s tpm2b;
+ tpm2b.size = sizeof(%(inner_type)s);
+ tpm2b.%(inner_name)s = inner;
+ return tpm2b;
+}
+"""
+
+ def __init__(self, name, is_union):
+ """Initializes a Structure instance.
+
+ Initially the instance will have no fields and no dependencies. Those can be
+ added with the AddField() and AddDependency() methods.
+
+ Args:
+ name: The name of the structure.
+ is_union: A boolean indicating whether this is a union.
+ """
+ self.name = name
+ self.is_union = is_union
+ self.fields = []
+ self.depends_on = []
+ self._forwarded = False
+
+ def AddField(self, field_type, field_name):
+ """Adds a field for this struct.
+
+ Args:
+ field_type: The type of the field.
+ field_name: The name of the field.
+ """
+ self.fields.append((field_type, FixName(field_name)))
+
+ def AddDependency(self, required_type):
+ """Adds an explicit dependency on another type.
+
+ This is used in cases where there is an additional dependency other than the
+ field types, which are implicit dependencies. For example, a field like
+ FIELD_TYPE value[sizeof(OTHER_TYPE)] would need OTHER_TYPE to be already
+ declared.
+
+ Args:
+ required_type: The type this structure depends on.
+ """
+ self.depends_on.append(required_type)
+
+ def IsSimpleTPM2B(self):
+ """Returns whether this struct is a TPM2B structure with raw bytes."""
+ return self.name.startswith('TPM2B_') and self.fields[1][0] == 'BYTE'
+
+ def IsComplexTPM2B(self):
+ """Returns whether this struct is a TPM2B structure with an inner struct."""
+ return self.name.startswith('TPM2B_') and self.fields[1][0] != 'BYTE'
+
+ def _GetFieldTypes(self):
+ """Creates a set which holds all current field types.
+
+ Returns:
+ A set of field types.
+ """
+ return set([field[0] for field in self.fields])
+
+ def OutputForward(self, out_file, unused_defined_types, unused_typemap):
+ """Writes a structure forward declaration to |out_file|.
+
+ This method needs to match the OutputForward method in other type classes
+ (e.g. Typedef) which is why the unused_* args exist.
+
+ Args:
+ out_file: The output file.
+ unused_defined_types: Not used.
+ unused_typemap: Not used.
+ """
+ if self._forwarded:
+ return
+ if self.is_union:
+ out_file.write(self._UNION_FORWARD % {'name': self.name})
+ else:
+ out_file.write(self._STRUCTURE_FORWARD % {'name': self.name})
+ self._forwarded = True
+
+ def Output(self, out_file, defined_types, typemap):
+ """Writes a structure definition to |out_file|.
+
+ Any outstanding dependencies will be defined.
+
+ Args:
+ out_file: The output file.
+ defined_types: A set of types for which definitions have already been
+ generated.
+ typemap: A dict mapping type names to the corresponding object.
+ """
+ if self.name in defined_types:
+ return
+ # Make sure any dependencies are already defined.
+ for field_type in self._GetFieldTypes():
+ if field_type not in defined_types:
+ typemap[field_type].Output(out_file, defined_types, typemap)
+ for required_type in self.depends_on:
+ if required_type not in defined_types:
+ typemap[required_type].Output(out_file, defined_types, typemap)
+ if self.is_union:
+ out_file.write(self._UNION % {'name': self.name})
+ else:
+ out_file.write(self._STRUCTURE % {'name': self.name})
+ for field in self.fields:
+ out_file.write(self._STRUCTURE_FIELD % {'type': field[0],
+ 'name': field[1]})
+ out_file.write(self._STRUCTURE_END)
+ defined_types.add(self.name)
+
+ def OutputSerialize(self, out_file, serialized_types, typemap):
+ """Writes serialize and parse functions for a structure to |out_file|.
+
+ Args:
+ out_file: The output file.
+ serialized_types: A set of types for which serialize and parse functions
+ have already been generated. This type name of this structure will be
+ added on success.
+ typemap: A dict mapping type names to the corresponding object.
+ """
+ if (self.name in serialized_types or
+ self.name == 'TPMU_NAME' or
+ self.name == 'TPMU_ENCRYPTED_SECRET'):
+ return
+ # Make sure any dependencies already have serialize functions defined.
+ for field_type in self._GetFieldTypes():
+ if field_type not in serialized_types:
+ typemap[field_type].OutputSerialize(out_file, serialized_types, typemap)
+ if self.is_union:
+ self._OutputUnionSerialize(out_file)
+ serialized_types.add(self.name)
+ return
+ out_file.write(self._SERIALIZE_FUNCTION_START % {'type': self.name})
+ if self.IsComplexTPM2B():
+ field_type = self.fields[1][0]
+ field_name = self.fields[1][1]
+ out_file.write(self._SERIALIZE_COMPLEX_TPM2B % {'type': field_type,
+ 'name': field_name})
+ else:
+ for field in self.fields:
+ if self._ARRAY_FIELD_RE.search(field[1]):
+ self._OutputArrayField(out_file, field, self._SERIALIZE_FIELD_ARRAY)
+ elif self._UNION_TYPE_RE.search(field[0]):
+ self._OutputUnionField(out_file, field,
+ self._SERIALIZE_FIELD_WITH_SELECTOR)
+ else:
+ out_file.write(self._SERIALIZE_FIELD % {'type': field[0],
+ 'name': field[1]})
+ out_file.write(self._SERIALIZE_FUNCTION_END)
+ out_file.write(self._PARSE_FUNCTION_START % {'type': self.name})
+ for field in self.fields:
+ if self._ARRAY_FIELD_RE.search(field[1]):
+ self._OutputArrayField(out_file, field, self._PARSE_FIELD_ARRAY)
+ elif self._UNION_TYPE_RE.search(field[0]):
+ self._OutputUnionField(out_file, field, self._PARSE_FIELD_WITH_SELECTOR)
+ else:
+ out_file.write(self._PARSE_FIELD % {'type': field[0],
+ 'name': field[1]})
+ out_file.write(self._SERIALIZE_FUNCTION_END)
+ # If this is a TPM2B structure throw in a few convenience functions.
+ if self.IsSimpleTPM2B():
+ field_name = self._ARRAY_FIELD_RE.search(self.fields[1][1]).group(1)
+ out_file.write(self._SIMPLE_TPM2B_HELPERS % {'type': self.name,
+ 'buffer_name': field_name})
+ elif self.IsComplexTPM2B():
+ field_type = self.fields[1][0]
+ field_name = self.fields[1][1]
+ out_file.write(self._COMPLEX_TPM2B_HELPERS % {'type': self.name,
+ 'inner_type': field_type,
+ 'inner_name': field_name})
+ serialized_types.add(self.name)
+
+ def _OutputUnionSerialize(self, out_file):
+ """Writes serialize and parse functions for a union to |out_file|.
+
+ This is more complex than the struct case because only one field of the
+ union is serialized / parsed based on the value of a selector. Arrays are
+ also handled differently: the full size of the array is serialized instead
+ of looking for a field which specifies the count.
+
+ Args:
+ out_file: The output file
+ """
+ selector_type = union_selectors.GetUnionSelectorType(self.name)
+ selector_values = union_selectors.GetUnionSelectorValues(self.name)
+ field_types = {f[1]: f[0] for f in self.fields}
+ out_file.write(self._SERIALIZE_UNION_FUNCTION_START %
+ {'union_type': self.name, 'selector_type': selector_type})
+ for selector in selector_values:
+ field_name = FixName(union_selectors.GetUnionSelectorField(self.name,
+ selector))
+ if not field_name:
+ out_file.write(self._EMPTY_UNION_CASE % {'selector_value': selector})
+ continue
+ field_type = field_types[field_name]
+ array_match = self._ARRAY_FIELD_RE.search(field_name)
+ if array_match:
+ field_name = array_match.group(1)
+ count = array_match.group(2)
+ out_file.write(self._SERIALIZE_UNION_FIELD_ARRAY %
+ {'selector_value': selector,
+ 'count': count,
+ 'field_type': field_type,
+ 'field_name': field_name})
+ else:
+ out_file.write(self._SERIALIZE_UNION_FIELD %
+ {'selector_value': selector,
+ 'field_type': field_type,
+ 'field_name': field_name})
+ out_file.write(self._SERIALIZE_FUNCTION_END)
+ out_file.write(self._PARSE_UNION_FUNCTION_START %
+ {'union_type': self.name, 'selector_type': selector_type})
+ for selector in selector_values:
+ field_name = FixName(union_selectors.GetUnionSelectorField(self.name,
+ selector))
+ if not field_name:
+ out_file.write(self._EMPTY_UNION_CASE % {'selector_value': selector})
+ continue
+ field_type = field_types[field_name]
+ array_match = self._ARRAY_FIELD_RE.search(field_name)
+ if array_match:
+ field_name = array_match.group(1)
+ count = array_match.group(2)
+ out_file.write(self._PARSE_UNION_FIELD_ARRAY %
+ {'selector_value': selector,
+ 'count': count,
+ 'field_type': field_type,
+ 'field_name': field_name})
+ else:
+ out_file.write(self._PARSE_UNION_FIELD %
+ {'selector_value': selector,
+ 'field_type': field_type,
+ 'field_name': field_name})
+ out_file.write(self._SERIALIZE_FUNCTION_END)
+
+ def _OutputUnionField(self, out_file, field, code_format):
+ """Writes serialize / parse code for a union field.
+
+ In this case |self| may not necessarily represent a union but |field| does.
+ This requires that a field of an acceptable selector type appear somewhere
+ in the struct. The value of this field is used as the selector value when
+ calling the serialize / parse function for the union.
+
+ Args:
+ out_file: The output file.
+ field: The union field to be processed as a (type, name) tuple.
+ code_format: Must be (_SERIALIZE|_PARSE)_FIELD_WITH_SELECTOR
+ """
+ selector_types = union_selectors.GetUnionSelectorTypes(field[0])
+ selector_name = ''
+ for tmp in self.fields:
+ if tmp[0] in selector_types:
+ selector_name = tmp[1]
+ break
+ assert selector_name, 'Missing selector for %s in %s!' % (field[1],
+ self.name)
+ out_file.write(code_format % {'type': field[0],
+ 'selector_name': selector_name,
+ 'name': field[1]})
+
+ def _OutputArrayField(self, out_file, field, code_format):
+ """Writes serialize / parse code for an array field.
+
+ The allocated size of the array is ignored and a field which holds the
+ actual count of items in the array must exist. Only the number of items
+ represented by the value of that count field are serialized / parsed.
+
+ Args:
+ out_file: The output file.
+ field: The array field to be processed as a (type, name) tuple.
+ code_format: Must be (_SERIALIZE|_PARSE)_FIELD_ARRAY
+ """
+ field_name = self._ARRAY_FIELD_RE.search(field[1]).group(1)
+ for count_field in self.fields:
+ assert count_field != field, ('Missing count field for %s in %s!' %
+ (field[1], self.name))
+ if self._ARRAY_FIELD_SIZE_RE.search(count_field[1]):
+ out_file.write(code_format % {'count': count_field[1],
+ 'type': field[0],
+ 'name': field_name})
+ break
+
+
+class Define(object):
+ """Represents a preprocessor define.
+
+ Attributes:
+ name: The name being defined.
+ value: The value being assigned to the name.
+ """
+
+ _DEFINE = '#if !defined(%(name)s)\n#define %(name)s %(value)s\n#endif\n'
+
+ def __init__(self, name, value):
+ """Initializes a Define instance.
+
+ Args:
+ name: The name being defined.
+ value: The value being assigned to the name.
+ """
+ self.name = name
+ self.value = value
+
+ def Output(self, out_file):
+ """Writes a preprocessor define to |out_file|.
+
+ Args:
+ out_file: The output file.
+ """
+ out_file.write(self._DEFINE % {'name': self.name, 'value': self.value})
+
+
+class StructureParser(object):
+ """Structure definition parser.
+
+ The input text file is extracted from the PDF file containing the TPM
+ structures specification from the Trusted Computing Group. The syntax
+ of the text file is defined by extract_structures.sh.
+
+ - Parses typedefs to a list of Typedef objects.
+ - Parses constants to a list of Constant objects.
+ - Parses structs and unions to a list of Structure objects.
+ - Parses defines to a list of Define objects.
+
+ The parser also creates 'typemap' dict which maps every type to its generator
+ object. This typemap helps manage type dependencies.
+
+ Example usage:
+ parser = StructureParser(open('myfile'))
+ types, constants, structs, defines, typemap = parser.Parse()
+ """
+
+ # Compile regular expressions.
+ _BEGIN_TYPES_TOKEN = '_BEGIN_TYPES'
+ _BEGIN_CONSTANTS_TOKEN = '_BEGIN_CONSTANTS'
+ _BEGIN_STRUCTURES_TOKEN = '_BEGIN_STRUCTURES'
+ _BEGIN_UNIONS_TOKEN = '_BEGIN_UNIONS'
+ _BEGIN_DEFINES_TOKEN = '_BEGIN_DEFINES'
+ _END_TOKEN = '_END'
+ _OLD_TYPE_RE = re.compile(r'^_OLD_TYPE\s+(\w+)$')
+ _NEW_TYPE_RE = re.compile(r'^_NEW_TYPE\s+(\w+)$')
+ _CONSTANTS_SECTION_RE = re.compile(r'^_CONSTANTS.* (\w+)$')
+ _STRUCTURE_SECTION_RE = re.compile(r'^_STRUCTURE\s+(\w+)$')
+ _UNION_SECTION_RE = re.compile(r'^_UNION\s+(\w+)$')
+ _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
+ _NAME_RE = re.compile(r'^_NAME\s+([a-zA-Z0-9_()\[\]/\*\+\-]+)$')
+ _VALUE_RE = re.compile(r'^_VALUE\s+(.+)$')
+ _SIZEOF_RE = re.compile(r'^.*sizeof\(([a-zA-Z0-9_]*)\).*$')
+
+ def __init__(self, in_file):
+ """Initializes a StructureParser instance.
+
+ Args:
+ in_file: A file as returned by open() which has been opened for reading.
+ """
+ self._line = None
+ self._in_file = in_file
+
+ def _NextLine(self):
+ """Gets the next input line.
+
+ Returns:
+ The next input line if another line is available, None otherwise.
+ """
+ try:
+ self._line = self._in_file.next()
+ except StopIteration:
+ self._line = None
+
+ def Parse(self):
+ """Parse everything in a structures file.
+
+ Returns:
+ Lists of objects and a type-map as described in the class documentation.
+ Returns these in the following order: types, constants, structs, defines,
+ typemap.
+ """
+ self._NextLine()
+ types = []
+ constants = []
+ structs = []
+ defines = []
+ typemap = {}
+ while self._line:
+ if self._BEGIN_TYPES_TOKEN == self._line.rstrip():
+ types += self._ParseTypes(typemap)
+ elif self._BEGIN_CONSTANTS_TOKEN == self._line.rstrip():
+ constants += self._ParseConstants(types, typemap)
+ elif self._BEGIN_STRUCTURES_TOKEN == self._line.rstrip():
+ structs += self._ParseStructures(self._STRUCTURE_SECTION_RE, typemap)
+ elif self._BEGIN_UNIONS_TOKEN == self._line.rstrip():
+ structs += self._ParseStructures(self._UNION_SECTION_RE, typemap)
+ elif self._BEGIN_DEFINES_TOKEN == self._line.rstrip():
+ defines += self._ParseDefines()
+ else:
+ print('Invalid file format: %s' % self._line)
+ break
+ self._NextLine()
+ # Empty structs not handled by the extractor.
+ self._AddEmptyStruct('TPMU_SYM_DETAILS', True, structs, typemap)
+ # Defines which are used in TPM 2.0 Part 2 but not defined there.
+ defines.append(Define(
+ 'MAX_CAP_DATA', '(MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32))'))
+ defines.append(Define(
+ 'MAX_CAP_ALGS', '(TPM_ALG_LAST - TPM_ALG_FIRST + 1)'))
+ defines.append(Define(
+ 'MAX_CAP_HANDLES', '(MAX_CAP_DATA/sizeof(TPM_HANDLE))'))
+ defines.append(Define(
+ 'MAX_CAP_CC', '((TPM_CC_LAST - TPM_CC_FIRST) + 1)'))
+ defines.append(Define(
+ 'MAX_TPM_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))'))
+ defines.append(Define(
+ 'MAX_PCR_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT))'))
+ defines.append(Define(
+ 'MAX_ECC_CURVES', '(MAX_CAP_DATA/sizeof(TPM_ECC_CURVE))'))
+ defines.append(Define('HASH_COUNT', '3'))
+ return types, constants, structs, defines, typemap
+
+ def _AddEmptyStruct(self, name, is_union, structs, typemap):
+ """Adds an empty Structure object to |structs| and |typemap|.
+
+ Args:
+ name: The name to assign the new structure.
+ is_union: A boolean indicating whether the new structure is a union.
+ structs: A list of structures to which the new object is appended.
+ typemap: A map of type names to objects to which the new name and object
+ are added.
+ """
+ s = Structure(name, is_union)
+ structs.append(s)
+ typemap[name] = s
+ return
+
+ def _ParseTypes(self, typemap):
+ """Parses a typedefs section.
+
+ The current line should be _BEGIN_TYPES and the method will stop parsing
+ when an _END line is found.
+
+ Args:
+ typemap: A dictionary to which parsed types are added.
+
+ Returns:
+ A list of Typedef objects.
+ """
+ types = []
+ self._NextLine()
+ while self._END_TOKEN != self._line.rstrip():
+ match = self._OLD_TYPE_RE.search(self._line)
+ if not match:
+ print('Invalid old type: %s' % self._line)
+ return types
+ old_type = match.group(1)
+ self._NextLine()
+ match = self._NEW_TYPE_RE.search(self._line)
+ if not match:
+ print('Invalid new type: %s' % self._line)
+ return types
+ new_type = match.group(1)
+ t = Typedef(old_type, new_type)
+ types.append(t)
+ typemap[new_type] = t
+ self._NextLine()
+ return types
+
+ def _ParseConstants(self, types, typemap):
+ """Parses a constants section.
+
+ The current line should be _BEGIN_CONSTANTS and the method will stop parsing
+ when an _END line is found. Each group of constants has an associated type
+ alias. A Typedef object is created for each of these aliases and added to
+ both |types| and |typemap|.
+
+ Args:
+ types: A list of Typedef objects.
+ typemap: A dictionary to which parsed types are added.
+
+ Returns:
+ A list of Constant objects.
+ """
+ constants = []
+ self._NextLine()
+ while self._END_TOKEN != self._line.rstrip():
+ match = self._CONSTANTS_SECTION_RE.search(self._line)
+ if not match:
+ print('Invalid constants section: %s' % self._line)
+ return constants
+ constant_typename = match.group(1)
+ self._NextLine()
+ match = self._TYPE_RE.search(self._line)
+ if not match:
+ print('Invalid constants type: %s' % self._line)
+ return constants
+ constant_type = match.group(1)
+ # Create a typedef for the constant group name (e.g. TPM_RC).
+ typedef = Typedef(constant_type, constant_typename)
+ typemap[constant_typename] = typedef
+ types.append(typedef)
+ self._NextLine()
+ match = self._NAME_RE.search(self._line)
+ if not match:
+ print('Invalid constant name: %s' % self._line)
+ return constants
+ while match:
+ name = match.group(1)
+ self._NextLine()
+ match = self._VALUE_RE.search(self._line)
+ if not match:
+ print('Invalid constant value: %s' % self._line)
+ return constants
+ value = match.group(1)
+ constants.append(Constant(constant_typename, name, value))
+ self._NextLine()
+ match = self._NAME_RE.search(self._line)
+ return constants
+
+ def _ParseStructures(self, section_re, typemap):
+ """Parses structures and unions.
+
+ The current line should be _BEGIN_STRUCTURES or _BEGIN_UNIONS and the method
+ will stop parsing when an _END line is found.
+
+ Args:
+ section_re: The regular expression to use for matching section tokens.
+ typemap: A dictionary to which parsed types are added.
+
+ Returns:
+ A list of Structure objects.
+ """
+ structures = []
+ is_union = section_re == self._UNION_SECTION_RE
+ self._NextLine()
+ while self._END_TOKEN != self._line.rstrip():
+ match = section_re.search(self._line)
+ if not match:
+ print('Invalid structure section: %s' % self._line)
+ return structures
+ current_structure_name = match.group(1)
+ current_structure = Structure(current_structure_name, is_union)
+ self._NextLine()
+ match = self._TYPE_RE.search(self._line)
+ if not match:
+ print('Invalid field type: %s' % self._line)
+ return structures
+ while match:
+ field_type = match.group(1)
+ self._NextLine()
+ match = self._NAME_RE.search(self._line)
+ if not match:
+ print('Invalid field name: %s' % self._line)
+ return structures
+ field_name = match.group(1)
+ # If the field name includes 'sizeof(SOME_TYPE)', record the dependency
+ # on SOME_TYPE.
+ match = self._SIZEOF_RE.search(field_name)
+ if match:
+ current_structure.AddDependency(match.group(1))
+ # Manually change unfortunate names.
+ if field_name == 'xor':
+ field_name = 'xor_'
+ current_structure.AddField(field_type, field_name)
+ self._NextLine()
+ match = self._TYPE_RE.search(self._line)
+ structures.append(current_structure)
+ typemap[current_structure_name] = current_structure
+ return structures
+
+ def _ParseDefines(self):
+ """Parses preprocessor defines.
+
+ The current line should be _BEGIN_DEFINES and the method will stop parsing
+ when an _END line is found.
+
+ Returns:
+ A list of Define objects.
+ """
+ defines = []
+ self._NextLine()
+ while self._END_TOKEN != self._line.rstrip():
+ match = self._NAME_RE.search(self._line)
+ if not match:
+ print('Invalid name: %s' % self._line)
+ return defines
+ name = match.group(1)
+ self._NextLine()
+ match = self._VALUE_RE.search(self._line)
+ if not match:
+ print('Invalid value: %s' % self._line)
+ return defines
+ value = match.group(1)
+ defines.append(Define(name, value))
+ self._NextLine()
+ return defines
+
+
+class Command(object):
+ """Represents a TPM command.
+
+ Attributes:
+ name: The command name (e.g. 'TPM2_Startup').
+ command_code: The name of the command code constant (e.g. TPM2_CC_Startup).
+ request_args: A list to hold command input arguments. Each element is a dict
+ and has these keys:
+ 'type': The argument type.
+ 'name': The argument name.
+ 'command_code': The optional value of the command code constant.
+ 'description': Optional descriptive text for the argument.
+ response_args: A list identical in form to request_args but to hold command
+ output arguments.
+ """
+
+ _HANDLE_RE = re.compile(r'TPMI_.H_.*')
+ _CALLBACK_ARG = """
+ const %(method_name)sResponse& callback"""
+ _DELEGATE_ARG = """
+ AuthorizationDelegate* authorization_delegate"""
+ _SERIALIZE_ARG = """
+ std::string* serialized_command"""
+ _PARSE_ARG = """
+ const std::string& response"""
+ _SERIALIZE_FUNCTION_START = """
+TPM_RC Tpm::SerializeCommand_%(method_name)s(%(method_args)s) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;"""
+ _DECLARE_COMMAND_CODE = """
+ TPM_CC command_code = %(command_code)s;"""
+ _DECLARE_BOOLEAN = """
+ bool %(var_name)s = %(value)s;"""
+ _SERIALIZE_LOCAL_VAR = """
+ std::string %(var_name)s_bytes;
+ rc = Serialize_%(var_type)s(
+ %(var_name)s,
+ &%(var_name)s_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }"""
+ _ENCRYPT_PARAMETER = """
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = %(var_name)s_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ %(var_name)s_bytes.replace(2, std::string::npos, tmp);
+ }"""
+ _HASH_START = """
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));"""
+ _HASH_UPDATE = """
+ hash->Update(%(var_name)s.data(),
+ %(var_name)s.size());"""
+ _APPEND_COMMAND_HANDLE = """
+ handle_section_bytes += %(var_name)s_bytes;
+ command_size += %(var_name)s_bytes.size();"""
+ _APPEND_COMMAND_PARAMETER = """
+ parameter_section_bytes += %(var_name)s_bytes;
+ command_size += %(var_name)s_bytes.size();"""
+ _AUTHORIZE_COMMAND = """
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }"""
+ _SERIALIZE_FUNCTION_END = """
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+"""
+ _RESPONSE_PARSER_START = """
+TPM_RC Tpm::ParseResponse_%(method_name)s(%(method_args)s) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);"""
+ _PARSE_LOCAL_VAR = """
+ %(var_type)s %(var_name)s;
+ std::string %(var_name)s_bytes;
+ rc = Parse_%(var_type)s(
+ &buffer,
+ &%(var_name)s,
+ &%(var_name)s_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }"""
+ _PARSE_ARG_VAR = """
+ std::string %(var_name)s_bytes;
+ rc = Parse_%(var_type)s(
+ &buffer,
+ %(var_name)s,
+ &%(var_name)s_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }"""
+ _RESPONSE_ERROR_CHECK = """
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }"""
+ _RESPONSE_SECTION_SPLIT = """
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }"""
+ _AUTHORIZE_RESPONSE = """
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }"""
+ _DECRYPT_PARAMETER = """
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = %(var_name)s_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ %(var_name)s_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_%(var_type)s(
+ &%(var_name)s_bytes,
+ %(var_name)s,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }"""
+ _RESPONSE_PARSER_END = """
+ return TPM_RC_SUCCESS;
+}
+"""
+ _ERROR_CALLBACK_START = """
+void %(method_name)sErrorCallback(
+ const Tpm::%(method_name)sResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code"""
+ _ERROR_CALLBACK_ARG = """,
+ %(arg_type)s()"""
+ _ERROR_CALLBACK_END = """);
+}
+"""
+ _RESPONSE_CALLBACK_START = """
+void %(method_name)sResponseParser(
+ const Tpm::%(method_name)sResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(%(method_name)sErrorCallback, callback);"""
+ _DECLARE_ARG_VAR = """
+ %(var_type)s %(var_name)s;"""
+ _RESPONSE_CALLBACK_END = """
+ TPM_RC rc = Tpm::ParseResponse_%(method_name)s(
+ response,%(method_arg_names_out)s
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc%(method_arg_names_in)s);
+}
+"""
+ _ASYNC_METHOD = """
+void Tpm::%(method_name)s(%(method_args)s) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(%(method_name)sErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(%(method_name)sResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_%(method_name)s(%(method_arg_names)s
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+"""
+ _SYNC_METHOD = """
+TPM_RC Tpm::%(method_name)sSync(%(method_args)s) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_%(method_name)s(%(method_arg_names_in)s
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_%(method_name)s(
+ response,%(method_arg_names_out)s
+ authorization_delegate);
+ return rc;
+}
+"""
+
+ def __init__(self, name):
+ """Initializes a Command instance.
+
+ Initially the request_args and response_args attributes are not set.
+
+ Args:
+ name: The command name (e.g. 'TPM2_Startup').
+ """
+ self.name = name
+ self.command_code = ''
+ self.request_args = None
+ self.response_args = None
+
+ def OutputDeclarations(self, out_file):
+ """Prints method and callback declaration statements for this command.
+
+ Args:
+ out_file: The output file.
+ """
+ self._OutputCallbackSignature(out_file)
+ self._OutputMethodSignatures(out_file)
+
+ def OutputSerializeFunction(self, out_file):
+ """Generates a serialize function for the command inputs.
+
+ Args:
+ out_file: Generated code is written to this file.
+ """
+ # Categorize arguments as either handles or parameters.
+ handles, parameters = self._SplitArgs(self.request_args)
+ response_parameters = self._SplitArgs(self.response_args)[1]
+ out_file.write(self._SERIALIZE_FUNCTION_START % {
+ 'method_name': self._MethodName(),
+ 'method_args': self._SerializeArgs()})
+ out_file.write(self._DECLARE_COMMAND_CODE % {'command_code':
+ self.command_code})
+ out_file.write(self._DECLARE_BOOLEAN % {
+ 'var_name': 'is_command_parameter_encryption_possible',
+ 'value': GetCppBool(parameters and IsTPM2B(parameters[0]['type']))})
+ out_file.write(self._DECLARE_BOOLEAN % {
+ 'var_name': 'is_response_parameter_encryption_possible',
+ 'value': GetCppBool(response_parameters and
+ IsTPM2B(response_parameters[0]['type']))})
+ # Serialize the command code and all the handles and parameters.
+ out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_code',
+ 'var_type': 'TPM_CC'})
+ for arg in self.request_args:
+ out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': arg['name'],
+ 'var_type': arg['type']})
+ # Encrypt the first parameter (before doing authorization) if necessary.
+ if parameters and IsTPM2B(parameters[0]['type']):
+ out_file.write(self._ENCRYPT_PARAMETER % {'var_name':
+ parameters[0]['name']})
+ # Compute the command hash and construct handle and parameter sections.
+ out_file.write(self._HASH_START)
+ out_file.write(self._HASH_UPDATE % {'var_name': 'command_code_bytes'})
+ for handle in handles:
+ out_file.write(self._HASH_UPDATE % {'var_name':
+ '%s_name' % handle['name']})
+ out_file.write(self._APPEND_COMMAND_HANDLE % {'var_name':
+ handle['name']})
+ for parameter in parameters:
+ out_file.write(self._HASH_UPDATE % {'var_name':
+ '%s_bytes' % parameter['name']})
+ out_file.write(self._APPEND_COMMAND_PARAMETER % {'var_name':
+ parameter['name']})
+ # Do authorization based on the hash.
+ out_file.write(self._AUTHORIZE_COMMAND)
+ # Now that the tag and size are finalized, serialize those.
+ out_file.write(self._SERIALIZE_LOCAL_VAR %
+ {'var_name': 'tag',
+ 'var_type': 'TPMI_ST_COMMAND_TAG'})
+ out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_size',
+ 'var_type': 'UINT32'})
+ out_file.write(self._SERIALIZE_FUNCTION_END)
+
+ def OutputParseFunction(self, out_file):
+ """Generates a parse function for the command outputs.
+
+ Args:
+ out_file: Generated code is written to this file.
+ """
+ out_file.write(self._RESPONSE_PARSER_START % {
+ 'method_name': self._MethodName(),
+ 'method_args': self._ParseArgs()})
+ # Parse the header -- this should always exist.
+ out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'tag',
+ 'var_type': 'TPM_ST'})
+ out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'response_size',
+ 'var_type': 'UINT32'})
+ out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'response_code',
+ 'var_type': 'TPM_RC'})
+ # Handle the error case.
+ out_file.write(self._RESPONSE_ERROR_CHECK)
+ # Categorize arguments as either handles or parameters.
+ handles, parameters = self._SplitArgs(self.response_args)
+ # Parse any handles.
+ for handle in handles:
+ out_file.write(self._PARSE_ARG_VAR % {'var_name': handle['name'],
+ 'var_type': handle['type']})
+ # Setup a serialized command code which is needed for the response hash.
+ out_file.write(self._DECLARE_COMMAND_CODE % {'command_code':
+ self.command_code})
+ out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_code',
+ 'var_type': 'TPM_CC'})
+ # Split out the authorization section.
+ out_file.write(self._RESPONSE_SECTION_SPLIT)
+ # Compute the response hash.
+ out_file.write(self._HASH_START)
+ out_file.write(self._HASH_UPDATE % {'var_name': 'response_code_bytes'})
+ out_file.write(self._HASH_UPDATE % {'var_name': 'command_code_bytes'})
+ out_file.write(self._HASH_UPDATE % {'var_name': 'buffer'})
+ # Do authorization related stuff.
+ out_file.write(self._AUTHORIZE_RESPONSE)
+ # Parse response parameters.
+ for arg in parameters:
+ out_file.write(self._PARSE_ARG_VAR % {'var_name': arg['name'],
+ 'var_type': arg['type']})
+ if parameters and IsTPM2B(parameters[0]['type']):
+ out_file.write(self._DECRYPT_PARAMETER % {'var_name':
+ parameters[0]['name'],
+ 'var_type':
+ parameters[0]['type']})
+ out_file.write(self._RESPONSE_PARSER_END)
+
+ def OutputMethodImplementation(self, out_file):
+ """Generates the implementation of a Tpm class method for this command.
+
+ The method assembles a command to be sent unmodified to the TPM and invokes
+ the CommandTransceiver with the command. Errors are reported directly to the
+ response callback via the error callback (see OutputErrorCallback).
+
+ Args:
+ out_file: Generated code is written to this file.
+ """
+ out_file.write(self._ASYNC_METHOD % {
+ 'method_name': self._MethodName(),
+ 'method_args': self._AsyncArgs(),
+ 'method_arg_names': self._ArgNameList(self._RequestArgs(),
+ trailing_comma=True)})
+ out_file.write(self._SYNC_METHOD % {
+ 'method_name': self._MethodName(),
+ 'method_args': self._SyncArgs(),
+ 'method_arg_names_in': self._ArgNameList(self._RequestArgs(),
+ trailing_comma=True),
+ 'method_arg_names_out': self._ArgNameList(self.response_args,
+ trailing_comma=True)})
+
+ def OutputErrorCallback(self, out_file):
+ """Generates the implementation of an error callback for this command.
+
+ The error callback simply calls the command response callback with the error
+ as the first argument and default values for all other arguments.
+
+ Args:
+ out_file: Generated code is written to this file.
+ """
+ out_file.write(self._ERROR_CALLBACK_START % {'method_name':
+ self._MethodName()})
+ for arg in self.response_args:
+ out_file.write(self._ERROR_CALLBACK_ARG % {'arg_type': arg['type']})
+ out_file.write(self._ERROR_CALLBACK_END)
+
+ def OutputResponseCallback(self, out_file):
+ """Generates the implementation of a response callback for this command.
+
+ The response callback takes the unmodified response from the TPM, parses it,
+ and invokes the original response callback with the parsed response args.
+ Errors during parsing or from the TPM are reported directly to the response
+ callback via the error callback (see OutputErrorCallback).
+
+ Args:
+ out_file: Generated code is written to this file.
+ """
+ out_file.write(self._RESPONSE_CALLBACK_START % {'method_name':
+ self._MethodName()})
+ for arg in self.response_args:
+ out_file.write(self._DECLARE_ARG_VAR % {'var_type': arg['type'],
+ 'var_name': arg['name']})
+ out_file.write(self._RESPONSE_CALLBACK_END % {
+ 'method_name': self._MethodName(),
+ 'method_arg_names_in': self._ArgNameList(self.response_args,
+ leading_comma=True),
+ 'method_arg_names_out': self._ArgNameList(self.response_args,
+ prefix='&',
+ trailing_comma=True)})
+
+ def GetNumberOfRequestHandles(self):
+ """Returns the number of input handles for this command."""
+ return len(self._SplitArgs(self.request_args)[0])
+
+ def GetNumberOfResponseHandles(self):
+ """Returns the number of output handles for this command."""
+ return len(self._SplitArgs(self.response_args)[0])
+
+ def _OutputMethodSignatures(self, out_file):
+ """Prints method declaration statements for this command.
+
+ This includes a method to serialize a request, a method to parse a response,
+ and methods for synchronous and asynchronous calls.
+
+ Args:
+ out_file: The output file.
+ """
+ out_file.write(' static TPM_RC SerializeCommand_%s(%s);\n' % (
+ self._MethodName(), self._SerializeArgs()))
+ out_file.write(' static TPM_RC ParseResponse_%s(%s);\n' % (
+ self._MethodName(), self._ParseArgs()))
+ out_file.write(' virtual void %s(%s);\n' % (self._MethodName(),
+ self._AsyncArgs()))
+ out_file.write(' virtual TPM_RC %sSync(%s);\n' % (self._MethodName(),
+ self._SyncArgs()))
+
+ def _OutputCallbackSignature(self, out_file):
+ """Prints a callback typedef for this command.
+
+ Args:
+ out_file: The output file.
+ """
+ args = self._InputArgList(self.response_args)
+ if args:
+ args = ',' + args
+ args = '\n TPM_RC response_code' + args
+ out_file.write(' typedef base::Callback<void(%s)> %sResponse;\n' %
+ (args, self._MethodName()))
+
+ def _MethodName(self):
+ """Creates an appropriate generated method name for the command.
+
+ We use the command name without the TPM2_ prefix.
+
+ Returns:
+ The method name.
+ """
+ if not self.name.startswith('TPM2_'):
+ return self.name
+ return self.name[5:]
+
+ def _InputArgList(self, args):
+ """Formats a list of input arguments for use in a function declaration.
+
+ Args:
+ args: An argument list in the same form as the request_args and
+ response_args attributes.
+
+ Returns:
+ A string which can be used in a function declaration.
+ """
+ if args:
+ arg_list = ['const %(type)s& %(name)s' % a for a in args]
+ return '\n ' + ',\n '.join(arg_list)
+ return ''
+
+ def _OutputArgList(self, args):
+ """Formats a list of output arguments for use in a function declaration.
+
+ Args:
+ args: An argument list in the same form as the request_args and
+ response_args attributes.
+
+ Returns:
+ A string which can be used in a function declaration.
+ """
+ if args:
+ arg_list = ['%(type)s* %(name)s' % a for a in args]
+ return '\n ' + ',\n '.join(arg_list)
+ return ''
+
+ def _ArgNameList(self, args, prefix='', leading_comma=False,
+ trailing_comma=False):
+ """Formats a list of arguments for use in a function call statement.
+
+ Args:
+ args: An argument list in the same form as the request_args and
+ response_args attributes.
+ prefix: A prefix to be prepended to each argument.
+ leading_comma: Whether to include a comma before the first argument.
+ trailing_comma: Whether to include a comma after the last argument.
+
+ Returns:
+ A string which can be used in a function call statement.
+ """
+ if args:
+ arg_list = [(prefix + a['name']) for a in args]
+ header = ''
+ if leading_comma:
+ header = ','
+ trailer = ''
+ if trailing_comma:
+ trailer = ','
+ return header + '\n ' + ',\n '.join(arg_list) + trailer
+ return ''
+
+ def _SplitArgs(self, args):
+ """Splits a list of args into handles and parameters."""
+ handles = []
+ parameters = []
+ # These commands have handles that are serialized into the parameter
+ # section.
+ command_handle_parameters = {
+ 'TPM_CC_FlushContext': 'TPMI_DH_CONTEXT',
+ 'TPM_CC_Hash': 'TPMI_RH_HIERARCHY',
+ 'TPM_CC_LoadExternal': 'TPMI_RH_HIERARCHY',
+ 'TPM_CC_SequenceComplete': 'TPMI_RH_HIERARCHY',
+ }
+ # Handle type that appears in the handle section.
+ always_handle = set(['TPM_HANDLE'])
+ # Handle types that always appear as command parameters.
+ always_parameter = set(['TPMI_RH_ENABLES', 'TPMI_DH_PERSISTENT'])
+ if self.command_code in command_handle_parameters:
+ always_parameter.add(command_handle_parameters[self.command_code])
+ for arg in args:
+ if (arg['type'] in always_handle or
+ (self._HANDLE_RE.search(arg['type']) and
+ arg['type'] not in always_parameter)):
+ handles.append(arg)
+ else:
+ parameters.append(arg)
+ return handles, parameters
+
+ def _RequestArgs(self):
+ """Computes the argument list for a Tpm request.
+
+ For every handle argument a handle name argument is added.
+ """
+ handles, parameters = self._SplitArgs(self.request_args)
+ args = []
+ # Add a name argument for every handle. We'll need it to compute cpHash.
+ for handle in handles:
+ args.append(handle)
+ args.append({'type': 'std::string',
+ 'name': '%s_name' % handle['name']})
+ for parameter in parameters:
+ args.append(parameter)
+ return args
+
+ def _AsyncArgs(self):
+ """Returns a formatted argument list for an asynchronous method."""
+ args = self._InputArgList(self._RequestArgs())
+ if args:
+ args += ','
+ return (args + self._DELEGATE_ARG + ',' +
+ self._CALLBACK_ARG % {'method_name': self._MethodName()})
+
+ def _SyncArgs(self):
+ """Returns a formatted argument list for a synchronous method."""
+ request_arg_list = self._InputArgList(self._RequestArgs())
+ if request_arg_list:
+ request_arg_list += ','
+ response_arg_list = self._OutputArgList(self.response_args)
+ if response_arg_list:
+ response_arg_list += ','
+ return request_arg_list + response_arg_list + self._DELEGATE_ARG
+
+ def _SerializeArgs(self):
+ """Returns a formatted argument list for a request-serialize method."""
+ args = self._InputArgList(self._RequestArgs())
+ if args:
+ args += ','
+ return args + self._SERIALIZE_ARG + ',' + self._DELEGATE_ARG
+
+ def _ParseArgs(self):
+ """Returns a formatted argument list for a response-parse method."""
+ args = self._OutputArgList(self.response_args)
+ if args:
+ args = ',' + args
+ return self._PARSE_ARG + args + ',' + self._DELEGATE_ARG
+
+
+class CommandParser(object):
+ """Command definition parser.
+
+ The input text file is extracted from the PDF file containing the TPM
+ command specification from the Trusted Computing Group. The syntax
+ of the text file is defined by extract_commands.sh.
+ """
+
+ # Regular expressions to pull relevant bits from annotated lines.
+ _INPUT_START_RE = re.compile(r'^_INPUT_START\s+(\w+)$')
+ _OUTPUT_START_RE = re.compile(r'^_OUTPUT_START\s+(\w+)$')
+ _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
+ _NAME_RE = re.compile(r'^_NAME\s+(\w+)$')
+ # Pull the command code from a comment like: _COMMENT TPM_CC_Startup {NV}.
+ _COMMENT_CC_RE = re.compile(r'^_COMMENT\s+(TPM_CC_\w+).*$')
+ _COMMENT_RE = re.compile(r'^_COMMENT\s+(.*)')
+ # Args which are handled internally by the generated method.
+ _INTERNAL_ARGS = ('tag', 'Tag', 'commandSize', 'commandCode', 'responseSize',
+ 'responseCode', 'returnCode')
+
+ def __init__(self, in_file):
+ """Initializes a CommandParser instance.
+
+ Args:
+ in_file: A file as returned by open() which has been opened for reading.
+ """
+ self._line = None
+ self._in_file = in_file
+
+ def _NextLine(self):
+ """Gets the next input line.
+
+ Returns:
+ The next input line if another line is available, None otherwise.
+ """
+ try:
+ self._line = self._in_file.next()
+ except StopIteration:
+ self._line = None
+
+ def Parse(self):
+ """Parses everything in a commands file.
+
+ Returns:
+ A list of extracted Command objects.
+ """
+ commands = []
+ self._NextLine()
+ if self._line != '_BEGIN\n':
+ print('Invalid format for first line: %s\n' % self._line)
+ return commands
+ self._NextLine()
+
+ while self._line != '_END\n':
+ cmd = self._ParseCommand()
+ if not cmd:
+ break
+ commands.append(cmd)
+ return commands
+
+ def _ParseCommand(self):
+ """Parses inputs and outputs for a single TPM command.
+
+ Returns:
+ A single Command object.
+ """
+ match = self._INPUT_START_RE.search(self._line)
+ if not match:
+ print('Cannot match command input from line: %s\n' % self._line)
+ return None
+ name = match.group(1)
+ cmd = Command(name)
+ self._NextLine()
+ cmd.request_args = self._ParseCommandArgs(cmd)
+ match = self._OUTPUT_START_RE.search(self._line)
+ if not match or match.group(1) != name:
+ print('Cannot match command output from line: %s\n' % self._line)
+ return None
+ self._NextLine()
+ cmd.response_args = self._ParseCommandArgs(cmd)
+ request_var_names = set([arg['name'] for arg in cmd.request_args])
+ for arg in cmd.response_args:
+ if arg['name'] in request_var_names:
+ arg['name'] += '_out'
+ if not cmd.command_code:
+ print('Command code not found for %s' % name)
+ return None
+ return cmd
+
+ def _ParseCommandArgs(self, cmd):
+ """Parses a set of arguments for a command.
+
+ The arguments may be input or output arguments.
+
+ Args:
+ cmd: The current Command object. The command_code attribute will be set if
+ such a constant is parsed.
+
+ Returns:
+ A list of arguments in the same form as the Command.request_args and
+ Command.response_args attributes.
+ """
+ args = []
+ match = self._TYPE_RE.search(self._line)
+ while match:
+ arg_type = match.group(1)
+ self._NextLine()
+ match = self._NAME_RE.search(self._line)
+ if not match:
+ print('Cannot match argument name from line: %s\n' % self._line)
+ break
+ arg_name = match.group(1)
+ self._NextLine()
+ match = self._COMMENT_CC_RE.search(self._line)
+ if match:
+ cmd.command_code = match.group(1)
+ match = self._COMMENT_RE.search(self._line)
+ if match:
+ self._NextLine()
+ if arg_name not in self._INTERNAL_ARGS:
+ args.append({'type': arg_type,
+ 'name': FixName(arg_name)})
+ match = self._TYPE_RE.search(self._line)
+ return args
+
+
+def GenerateHandleCountFunctions(commands, out_file):
+ """Generates the GetNumberOf*Handles functions given a list of commands.
+
+ Args:
+ commands: A list of Command objects.
+ out_file: The output file.
+ """
+ out_file.write(_HANDLE_COUNT_FUNCTION_START % {'handle_type': 'Request'})
+ for command in commands:
+ out_file.write(_HANDLE_COUNT_FUNCTION_CASE %
+ {'command_code': command.command_code,
+ 'handle_count': command.GetNumberOfRequestHandles()})
+ out_file.write(_HANDLE_COUNT_FUNCTION_END)
+ out_file.write(_HANDLE_COUNT_FUNCTION_START % {'handle_type': 'Response'})
+ for command in commands:
+ out_file.write(_HANDLE_COUNT_FUNCTION_CASE %
+ {'command_code': command.command_code,
+ 'handle_count': command.GetNumberOfResponseHandles()})
+ out_file.write(_HANDLE_COUNT_FUNCTION_END)
+
+
+def GenerateHeader(types, constants, structs, defines, typemap, commands):
+ """Generates a header file with declarations for all given generator objects.
+
+ Args:
+ types: A list of Typedef objects.
+ constants: A list of Constant objects.
+ structs: A list of Structure objects.
+ defines: A list of Define objects.
+ typemap: A dict mapping type names to the corresponding object.
+ commands: A list of Command objects.
+ """
+ out_file = open(_OUTPUT_FILE_H, 'w')
+ out_file.write(_COPYRIGHT_HEADER)
+ guard_name = 'TRUNKS_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_')
+ out_file.write(_HEADER_FILE_GUARD_HEADER % {'name': guard_name})
+ out_file.write(_HEADER_FILE_INCLUDES)
+ out_file.write(_NAMESPACE_BEGIN)
+ out_file.write(_FORWARD_DECLARATIONS)
+ out_file.write('\n')
+ # These types are built-in or defined by <stdint.h>; they serve as base cases
+ # when defining type dependencies.
+ defined_types = set(_BASIC_TYPES)
+ # Generate defines. These must be generated before any other code.
+ for define in defines:
+ define.Output(out_file)
+ out_file.write('\n')
+ # Generate typedefs. These are declared before structs because they are not
+ # likely to depend on structs and when they do a simple forward declaration
+ # for the struct can be generated. This improves the readability of the
+ # generated code.
+ for typedef in types:
+ typedef.Output(out_file, defined_types, typemap)
+ out_file.write('\n')
+ # Generate constant definitions. Again, generated before structs to improve
+ # readability.
+ for constant in constants:
+ constant.Output(out_file, defined_types, typemap)
+ out_file.write('\n')
+ # Generate structs. All non-struct dependencies should be already declared.
+ for struct in structs:
+ struct.Output(out_file, defined_types, typemap)
+ # Helper function declarations.
+ out_file.write(_FUNCTION_DECLARATIONS)
+ # Generate serialize / parse function declarations.
+ for basic_type in _BASIC_TYPES:
+ out_file.write(_SERIALIZE_DECLARATION % {'type': basic_type})
+ for typedef in types:
+ out_file.write(_SERIALIZE_DECLARATION % {'type': typedef.new_type})
+ for struct in structs:
+ out_file.write(_SERIALIZE_DECLARATION % {'type': struct.name})
+ if struct.IsSimpleTPM2B():
+ out_file.write(_SIMPLE_TPM2B_HELPERS_DECLARATION % {'type': struct.name})
+ elif struct.IsComplexTPM2B():
+ out_file.write(_COMPLEX_TPM2B_HELPERS_DECLARATION % {
+ 'type': struct.name,
+ 'inner_type': struct.fields[1][0]})
+ # Generate a declaration for a 'Tpm' class, which includes one method for
+ # every TPM 2.0 command.
+ out_file.write(_CLASS_BEGIN)
+ for command in commands:
+ command.OutputDeclarations(out_file)
+ out_file.write(_CLASS_END)
+ out_file.write(_NAMESPACE_END)
+ out_file.write(_HEADER_FILE_GUARD_FOOTER % {'name': guard_name})
+ out_file.close()
+
+
+def GenerateImplementation(types, structs, typemap, commands):
+ """Generates implementation code for each command.
+
+ Args:
+ types: A list of Typedef objects.
+ structs: A list of Structure objects.
+ typemap: A dict mapping type names to the corresponding object.
+ commands: A list of Command objects.
+ """
+ out_file = open(_OUTPUT_FILE_CC, 'w')
+ out_file.write(_COPYRIGHT_HEADER)
+ out_file.write(_LOCAL_INCLUDE % {'filename': _OUTPUT_FILE_H})
+ out_file.write(_IMPLEMENTATION_FILE_INCLUDES)
+ out_file.write(_NAMESPACE_BEGIN)
+ GenerateHandleCountFunctions(commands, out_file)
+ serialized_types = set(_BASIC_TYPES)
+ for basic_type in _BASIC_TYPES:
+ out_file.write(_SERIALIZE_BASIC_TYPE % {'type': basic_type})
+ for typedef in types:
+ typedef.OutputSerialize(out_file, serialized_types, typemap)
+ for struct in structs:
+ struct.OutputSerialize(out_file, serialized_types, typemap)
+ for command in commands:
+ command.OutputSerializeFunction(out_file)
+ command.OutputParseFunction(out_file)
+ command.OutputErrorCallback(out_file)
+ command.OutputResponseCallback(out_file)
+ command.OutputMethodImplementation(out_file)
+ out_file.write(_NAMESPACE_END)
+ out_file.close()
+
+
+def main():
+ """A main function.
+
+ Both a TPM structures file and commands file are parsed and C++ header and C++
+ implementation file are generated.
+
+ Positional Args:
+ structures_file: The extracted TPM structures file.
+ commands_file: The extracted TPM commands file.
+ """
+ parser = argparse.ArgumentParser(description='TPM 2.0 code generator')
+ parser.add_argument('structures_file')
+ parser.add_argument('commands_file')
+ args = parser.parse_args()
+ structure_parser = StructureParser(open(args.structures_file))
+ types, constants, structs, defines, typemap = structure_parser.Parse()
+ command_parser = CommandParser(open(args.commands_file))
+ commands = command_parser.Parse()
+ GenerateHeader(types, constants, structs, defines, typemap, commands)
+ GenerateImplementation(types, structs, typemap, commands)
+ print('Processed %d commands.' % len(commands))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/trunks/generator/generator_test.py b/trunks/generator/generator_test.py
new file mode 100755
index 0000000..e8a5901
--- /dev/null
+++ b/trunks/generator/generator_test.py
@@ -0,0 +1,256 @@
+#!/usr/bin/python
+
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+"""Unit tests for the TPM 2.0 code generator."""
+
+from __future__ import print_function
+
+import StringIO
+import unittest
+
+import generator
+
+
+class TestGenerators(unittest.TestCase):
+ """Test generator classes."""
+
+ def testTypedef(self):
+ """Test generation of typedefs and dependencies."""
+ typedef = generator.Typedef('int', 'INT')
+ defined_types = set(['int'])
+ typemap = {}
+ out_file = StringIO.StringIO()
+ # Expect this to just write the typedef.
+ typedef.OutputForward(out_file, defined_types, typemap)
+ # Expect this to know it has already been written.
+ typedef.Output(out_file, defined_types, typemap)
+ self.assertEqual(out_file.getvalue(), 'typedef int INT;\n')
+ self.assertIn('INT', defined_types)
+ typedef2 = generator.Typedef('TYPE1', 'TYPE2')
+ typemap = {'TYPE1': generator.Structure('TYPE1', False)}
+ defined_types = set([])
+ out_file2 = StringIO.StringIO()
+ # Expect this to write first TYPE1 forward then TYPE2 typedef.
+ typedef2.Output(out_file2, defined_types, typemap)
+ output_re = r'struct TYPE1;\s+typedef TYPE1 TYPE2;\s+'
+ self.assertRegexpMatches(out_file2.getvalue(), output_re)
+ self.assertIn('TYPE2', defined_types)
+ out_file.close()
+ out_file2.close()
+
+ def testTypedefSerialize(self):
+ """Test generation of serialization code for typedefs."""
+ serialized_types = set(['int'])
+ typedef = generator.Typedef('int', 'INT')
+ typedef2 = generator.Typedef('INT', 'INT2')
+ typemap = {'INT': typedef}
+ out_file = StringIO.StringIO()
+ typedef2.OutputSerialize(out_file, serialized_types, typemap)
+ self.assertIn('INT', serialized_types)
+ self.assertIn('INT2', serialized_types)
+ out_file.close()
+
+ def testConstant(self):
+ """Test generation of constant definitions and type dependencies."""
+ constant = generator.Constant('INT', 'test', '1')
+ typemap = {'INT': generator.Structure('INT', False)}
+ defined_types = set([])
+ out_file = StringIO.StringIO()
+ constant.Output(out_file, defined_types, typemap)
+ output_re = r'struct INT;\s+const INT test = 1;\s+'
+ self.assertRegexpMatches(out_file.getvalue(), output_re)
+ out_file.close()
+
+ def testStructure(self):
+ """Test generation of structure declarations and field dependencies."""
+ struct = generator.Structure('STRUCT', False)
+ struct.AddField('int', 'i')
+ struct.AddDependency('DEPEND')
+ union = generator.Structure('UNION', True)
+ union.AddField('STRUCT', 'inner')
+ depend = generator.Structure('DEPEND', False)
+ defined_types = set(['int'])
+ out_file = StringIO.StringIO()
+ typemap = {'STRUCT': struct, 'DEPEND': depend}
+ # Only output |union|, this will test the dependency logic.
+ union.OutputForward(out_file, defined_types, typemap)
+ union.OutputForward(out_file, defined_types, typemap)
+ union.Output(out_file, defined_types, typemap)
+ output_re = r'union UNION;\s+struct DEPEND {\s+};\s+'
+ output_re += r'struct STRUCT {\s+int i;\s+};\s+'
+ output_re += r'union UNION {\s+STRUCT inner;\s+};\s+'
+ self.assertRegexpMatches(out_file.getvalue(), output_re)
+ for t in ('STRUCT', 'DEPEND', 'UNION'):
+ self.assertIn(t, defined_types)
+ # Test serialize / parse code generation.
+ out_file.close()
+
+ def testStructSerialize(self):
+ """Test generation of serialization code for typedefs."""
+ serialized_types = set(['int', 'FOO', 'BAR', 'TPMI_ALG_SYM_OBJECT'])
+ struct = generator.Structure('TEST_STRUCT', False)
+ struct.fields = [('TPMI_ALG_SYM_OBJECT', 'selector'),
+ ('TPMU_SYM_MODE', 'mode'),
+ ('int', 'sizeOfFoo'),
+ ('int', 'foo[FOO_MAX]')]
+ # Choose TPMU_SYM_MODE because it exists in the selectors definition and it
+ # has few fields.
+ union = generator.Structure('TPMU_SYM_MODE', True)
+ union.fields = [('FOO', 'aes'), ('BAR', 'sm4')]
+ typemap = {'TPMU_SYM_MODE': union}
+ out_file = StringIO.StringIO()
+ struct.OutputSerialize(out_file, serialized_types, typemap)
+ self.assertIn('TPMU_SYM_MODE', serialized_types)
+ self.assertIn('TEST_STRUCT', serialized_types)
+ out_file.close()
+
+ def testDefine(self):
+ """Test generation of preprocessor defines."""
+ define = generator.Define('name', 'value')
+ out_file = StringIO.StringIO()
+ define.Output(out_file)
+ output_re = r'#if !defined\(name\)\s+#define name value\s+#endif\s+'
+ self.assertRegexpMatches(out_file.getvalue(), output_re)
+ out_file.close()
+
+ def _MakeArg(self, arg_type, arg_name):
+ return {'type': arg_type,
+ 'name': arg_name,
+ 'command_code': None,
+ 'description': None}
+
+ def testCommand(self):
+ """Test generation of command methods and callbacks."""
+ command = generator.Command('TPM2_Test')
+ command.request_args = [self._MakeArg('int', 'input')]
+ command.response_args = [self._MakeArg('char', 'output')]
+ out_file = StringIO.StringIO()
+ command.OutputDeclarations(out_file)
+ expected_callback = """typedef base::Callback<void(
+ TPM_RC response_code,
+ const char& output)> TestResponse;"""
+ self.assertIn(expected_callback, out_file.getvalue())
+ expected_serialize = """static TPM_RC SerializeCommand_Test(
+ const int& input,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);"""
+ self.assertIn(expected_serialize, out_file.getvalue())
+ expected_parse = """static TPM_RC ParseResponse_Test(
+ const std::string& response,
+ char* output,
+ AuthorizationDelegate* authorization_delegate);"""
+ self.assertIn(expected_parse, out_file.getvalue())
+ expected_async = """virtual void Test(
+ const int& input,
+ AuthorizationDelegate* authorization_delegate,
+ const TestResponse& callback);"""
+ self.assertIn(expected_async, out_file.getvalue())
+ expected_sync = """virtual TPM_RC TestSync(
+ const int& input,
+ char* output,
+ AuthorizationDelegate* authorization_delegate);"""
+ self.assertIn(expected_sync, out_file.getvalue())
+ out_file.close()
+
+
+class TestParsers(unittest.TestCase):
+ """Test parser classes."""
+
+ FAKE_TYPEDEF = '_BEGIN_TYPES\n_OLD_TYPE type1\n_NEW_TYPE type2\n_END\n'
+ FAKE_CONSTANT = ('_BEGIN_CONSTANTS\n_CONSTANTS (base_type) const_type\n'
+ '_TYPE base_type\n_NAME const_name\n_VALUE const_value\n'
+ '_END\n')
+ FAKE_STRUCTURE = ('_BEGIN_STRUCTURES\n_STRUCTURE struct_type\n'
+ '_TYPE field_type\n'
+ '_NAME field_name[sizeof(depend_type)]\n_END\n')
+ FAKE_DEFINE = '_BEGIN_DEFINES\n_NAME define_name\n_VALUE define_value\n_END'
+ FAKE_COMMAND = ('_BEGIN\n_INPUT_START TPM2_Test\n'
+ '_TYPE UINT32\n_NAME commandSize\n'
+ '_TYPE TPM_CC\n_NAME commandCode\n_COMMENT TPM_CC_Test\n'
+ '_TYPE UINT16\n_NAME input\n'
+ '_OUTPUT_START TPM2_Test\n_END\n')
+
+ def testStructureParserWithBadData(self):
+ """Test the structure parser with invalid data."""
+ input_data = 'bad_data'
+ in_file = StringIO.StringIO(input_data)
+ parser = generator.StructureParser(in_file)
+ types, constants, structs, defines, typemap = parser.Parse()
+ self.assertIsNotNone(types)
+ self.assertIsNotNone(constants)
+ self.assertIsNotNone(structs)
+ self.assertIsNotNone(defines)
+ self.assertIsNotNone(typemap)
+
+ def testStructureParser(self):
+ """Test the structure parser with valid data."""
+ input_data = (self.FAKE_TYPEDEF + self.FAKE_CONSTANT + self.FAKE_STRUCTURE +
+ self.FAKE_DEFINE)
+ in_file = StringIO.StringIO(input_data)
+ parser = generator.StructureParser(in_file)
+ types, constants, structs, defines, typemap = parser.Parse()
+ # Be flexible on these counts because the parser may add special cases.
+ self.assertGreaterEqual(len(types), 2)
+ self.assertGreaterEqual(len(constants), 1)
+ self.assertGreaterEqual(len(structs), 1)
+ self.assertGreaterEqual(len(defines), 1)
+ self.assertGreaterEqual(len(typemap), 3)
+ self.assertEqual(types[0].old_type, 'type1')
+ self.assertEqual(types[0].new_type, 'type2')
+ self.assertEqual(types[1].old_type, 'base_type')
+ self.assertEqual(types[1].new_type, 'const_type')
+ self.assertEqual(constants[0].const_type, 'const_type')
+ self.assertEqual(constants[0].name, 'const_name')
+ self.assertEqual(constants[0].value, 'const_value')
+ self.assertEqual(structs[0].name, 'struct_type')
+ self.assertEqual(structs[0].is_union, False)
+ self.assertEqual(len(structs[0].fields), 1)
+ self.assertEqual(structs[0].fields[0][0], 'field_type')
+ self.assertEqual(structs[0].fields[0][1], 'field_name[sizeof(depend_type)]')
+ self.assertEqual(len(structs[0].depends_on), 1)
+ self.assertEqual(structs[0].depends_on[0], 'depend_type')
+ self.assertEqual(defines[0].name, 'define_name')
+ self.assertEqual(defines[0].value, 'define_value')
+
+ def testCommandParserWithBadData(self):
+ """Test the command parser with invalid data."""
+ input_data = 'bad_data'
+ in_file = StringIO.StringIO(input_data)
+ parser = generator.CommandParser(in_file)
+ commands = parser.Parse()
+ self.assertIsNotNone(commands)
+
+ def testCommandParser(self):
+ """Test the command parser with valid data."""
+ input_data = self.FAKE_COMMAND
+ in_file = StringIO.StringIO(input_data)
+ parser = generator.CommandParser(in_file)
+ commands = parser.Parse()
+ self.assertEqual(len(commands), 1)
+ self.assertEqual(commands[0].name, 'TPM2_Test')
+ self.assertEqual(commands[0].command_code, 'TPM_CC_Test')
+ # We expect the 'commandSize' and 'commandCode' args to be filtered out.
+ self.assertEqual(len(commands[0].request_args), 1)
+ self.assertEqual(commands[0].request_args[0]['type'], 'UINT16')
+ self.assertEqual(commands[0].request_args[0]['name'], 'input')
+ self.assertIsNotNone(commands[0].response_args)
+ self.assertFalse(commands[0].response_args)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/trunks/generator/raw_commands.txt b/trunks/generator/raw_commands.txt
new file mode 100644
index 0000000..f9d995a
--- /dev/null
+++ b/trunks/generator/raw_commands.txt
@@ -0,0 +1,35656 @@
+Trusted Platform Module Library
+Part 3: Commands
+Family “2.0”
+Level 00 Revision 00.99
+October 31, 2013
+
+Contact: admin@trustedcomputinggroup.org
+
+Published
+Copyright © TCG 2006-2013
+
+TCG
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Licenses and Notices
+1. Copyright Licenses:
+
+
+Trusted Computing Group (TCG) grants to the user of the source code in this specification (the
+“Source Code”) a worldwide, irrevocable, nonexclusive, royalty free, copyright license to
+reproduce, create derivative works, distribute, display and perform the Source Code and
+derivative works thereof, and to grant others the rights granted herein.
+
+
+
+The TCG grants to the user of the other parts of the specification (other than the Source Code)
+the rights to reproduce, distribute, display, and perform the specification solely for the purpose of
+developing products based on such documents.
+
+2. Source Code Distribution Conditions:
+
+
+Redistributions of Source Code must retain the above copyright licenses, this list of conditions
+and the following disclaimers.
+
+
+
+Redistributions in binary form must reproduce the above copyright licenses, this list of conditions
+and the following disclaimers in the documentation and/or other materials provided with the
+distribution.
+
+3. Disclaimers:
+
+
+THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF
+LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH
+RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)
+THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.
+Contact TCG Administration (admin@trustedcomputinggroup.org) for information on specification
+licensing rights available through TCG membership agreements.
+
+
+
+THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES
+WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF
+INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF
+ANY PROPOSAL, SPECIFICATION OR SAMPLE.
+
+
+
+Without limitation, TCG and its members and licensors disclaim all liability, including liability for
+infringement of any proprietary rights, relating to use of information in this specification and to the
+implementation of this specification, and TCG disclaims all liability for cost of procurement of
+substitute goods or services, lost profits, loss of use, loss of data or any incidental, consequential,
+direct, indirect, or special damages, whether under contract, tort, warranty or otherwise, arising in
+any way out of use or reliance upon this specification or any information herein.
+
+Any marks and brands contained herein are the property of their respective owner
+
+Page ii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+CONTENTS
+1
+2
+3
+4
+
+Scope .................................................................................................................................................... 1
+Terms and Definitions ........................................................................................................................... 1
+Symbols and abbreviated terms ............................................................................................................ 1
+Notation ................................................................................................................................................. 1
+4.1
+4.2
+4.3
+4.4
+
+5
+6
+7
+
+Introduction ..................................................................................................................................... 1
+Table Decorations ........................................................................................................................... 1
+Handle and Parameter Demarcation .............................................................................................. 3
+AuthorizationSize and ParameterSize ............................................................................................ 3
+
+Normative References ........................................................................................................................... 4
+Symbols and Abbreviated Terms .......................................................................................................... 4
+Command Processing ........................................................................................................................... 4
+7.1
+7.2
+7.3
+7.4
+7.5
+7.6
+7.7
+7.8
+7.9
+
+8
+
+Introduction ..................................................................................................................................... 4
+Command Header Validation .......................................................................................................... 4
+Mode Checks .................................................................................................................................. 4
+Handle Area Validation ................................................................................................................... 5
+Session Area Validation .................................................................................................................. 6
+Authorization Checks ...................................................................................................................... 7
+Parameter Decryption ..................................................................................................................... 8
+Parameter Unmarshaling ................................................................................................................ 9
+Command Post Processing .......................................................................................................... 10
+
+Response Values ................................................................................................................................ 12
+8.1
+8.2
+
+9
+10
+
+Implementation Dependent ................................................................................................................. 15
+Detailed Actions Assumptions ............................................................................................................. 16
+
+10.1
+10.2
+10.3
+11
+
+Introduction ................................................................................................................................... 28
+TPM2_SelfTest ............................................................................................................................. 29
+TPM2_IncrementalSelfTest .......................................................................................................... 32
+TPM2_GetTestResult ................................................................................................................... 35
+
+Session Commands ............................................................................................................................ 38
+
+13.1
+13.2
+14
+
+Introduction ................................................................................................................................... 17
+_TPM_Init...................................................................................................................................... 17
+TPM2_Startup ............................................................................................................................... 19
+TPM2_Shutdown .......................................................................................................................... 24
+
+Testing ................................................................................................................................................. 28
+
+12.1
+12.2
+12.3
+12.4
+13
+
+Introduction ................................................................................................................................... 16
+Pre-processing .............................................................................................................................. 16
+Post Processing ............................................................................................................................ 16
+
+Start-up ................................................................................................................................................ 17
+
+11.1
+11.2
+11.3
+11.4
+12
+
+Tag ................................................................................................................................................ 12
+Response Codes .......................................................................................................................... 12
+
+TPM2_StartAuthSession .............................................................................................................. 38
+TPM2_PolicyRestart ..................................................................................................................... 43
+
+Object Commands............................................................................................................................... 46
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page iii
+October 31, 2013
+
+ Part 3: Commands
+14.1
+14.2
+14.3
+14.4
+14.5
+14.6
+14.7
+14.8
+15
+
+Introduction ................................................................................................................................. 132
+TPM2_HMAC_Start .................................................................................................................... 132
+TPM2_HashSequenceStart ........................................................................................................ 136
+TPM2_SequenceUpdate ............................................................................................................ 139
+TPM2_SequenceComplete......................................................................................................... 143
+TPM2_EventSequenceComplete ............................................................................................... 147
+
+Attestation Commands ...................................................................................................................... 151
+
+20.1
+20.2
+20.3
+20.4
+20.5
+20.6
+20.7
+21
+
+TPM2_GetRandom ..................................................................................................................... 126
+TPM2_StirRandom ..................................................................................................................... 129
+
+Hash/HMAC/Event Sequences ......................................................................................................... 132
+
+19.1
+19.2
+19.3
+19.4
+19.5
+19.6
+20
+
+Introduction ................................................................................................................................. 113
+TPM2_EncryptDecrypt ................................................................................................................ 115
+TPM2_Hash ................................................................................................................................ 119
+TPM2_HMAC .............................................................................................................................. 122
+
+Random Number Generator .............................................................................................................. 126
+
+18.1
+18.2
+19
+
+Introduction ................................................................................................................................... 92
+TPM2_RSA_Encrypt ..................................................................................................................... 92
+TPM2_RSA_Decrypt .................................................................................................................... 97
+TPM2_ECDH_KeyGen ............................................................................................................... 101
+TPM2_ECDH_ZGen ................................................................................................................... 104
+TPM2_ECC_Parameters ............................................................................................................ 107
+TPM2_ZGen_2Phase ................................................................................................................. 108
+
+Symmetric Primitives ......................................................................................................................... 113
+
+17.1
+17.2
+17.3
+17.4
+18
+
+TPM2_Duplicate ........................................................................................................................... 77
+TPM2_Rewrap .............................................................................................................................. 81
+TPM2_Import ................................................................................................................................ 86
+
+Asymmetric Primitives ......................................................................................................................... 92
+
+16.1
+16.2
+16.3
+16.4
+16.5
+16.6
+16.7
+17
+
+TPM2_Create................................................................................................................................ 46
+TPM2_Load .................................................................................................................................. 51
+TPM2_LoadExternal ..................................................................................................................... 55
+TPM2_ReadPublic ........................................................................................................................ 60
+TPM2_ActivateCredential ............................................................................................................. 63
+TPM2_MakeCredential ................................................................................................................. 67
+TPM2_Unseal ............................................................................................................................... 70
+TPM2_ObjectChangeAuth ............................................................................................................ 73
+
+Duplication Commands ....................................................................................................................... 77
+
+15.1
+15.2
+15.3
+16
+
+Trusted Platform Module Library
+
+Introduction ................................................................................................................................. 151
+TPM2_Certify .............................................................................................................................. 153
+TPM2_CertifyCreation ................................................................................................................ 157
+TPM2_Quote............................................................................................................................... 161
+TPM2_GetSessionAuditDigest ................................................................................................... 165
+TPM2_GetCommandAuditDigest ............................................................................................... 169
+TPM2_GetTime........................................................................................................................... 173
+
+Ephemeral EC Keys .......................................................................................................................... 177
+
+Page iv
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+21.1
+21.2
+21.3
+22
+
+Introduction ................................................................................................................................. 200
+TPM2_PCR_Extend ................................................................................................................... 201
+TPM2_PCR_Event ..................................................................................................................... 204
+TPM2_PCR_Read ...................................................................................................................... 207
+TPM2_PCR_Allocate .................................................................................................................. 210
+TPM2_PCR_SetAuthPolicy ........................................................................................................ 213
+TPM2_PCR_SetAuthValue ......................................................................................................... 216
+TPM2_PCR_Reset ..................................................................................................................... 219
+_TPM_Hash_Start ...................................................................................................................... 222
+_TPM_Hash_Data ...................................................................................................................... 224
+_TPM_Hash_End ....................................................................................................................... 226
+
+Enhanced Authorization (EA) Commands ........................................................................................ 229
+
+25.1
+25.2
+25.3
+25.4
+25.5
+25.6
+25.7
+25.8
+25.9
+25.10
+25.11
+25.12
+25.13
+25.14
+25.15
+25.16
+25.17
+25.18
+25.19
+25.20
+26
+
+Introduction ................................................................................................................................. 195
+TPM2_SetCommandCodeAuditStatus ....................................................................................... 196
+
+Integrity Collection (PCR) .................................................................................................................. 200
+
+24.1
+24.2
+24.3
+24.4
+24.5
+24.6
+24.7
+24.8
+24.9
+24.10
+24.11
+25
+
+TPM2_VerifySignature ................................................................................................................ 187
+TPM2_Sign ................................................................................................................................. 191
+
+Command Audit ................................................................................................................................. 195
+
+23.1
+23.2
+24
+
+Introduction ................................................................................................................................. 177
+TPM2_Commit ............................................................................................................................ 178
+TPM2_EC_Ephemeral ................................................................................................................ 184
+
+Signing and Signature Verification .................................................................................................... 187
+
+22.1
+22.2
+23
+
+Part 3: Commands
+
+Introduction ................................................................................................................................. 229
+Signed Authorization Actions ...................................................................................................... 230
+TPM2_PolicySigned ................................................................................................................... 234
+TPM2_PolicySecret .................................................................................................................... 240
+TPM2_PolicyTicket ..................................................................................................................... 244
+TPM2_PolicyOR ......................................................................................................................... 248
+TPM2_PolicyPCR ....................................................................................................................... 252
+TPM2_PolicyLocality .................................................................................................................. 256
+TPM2_PolicyNV .......................................................................................................................... 260
+TPM2_PolicyCounterTimer......................................................................................................... 265
+TPM2_PolicyCommandCode ..................................................................................................... 270
+TPM2_PolicyPhysicalPresence .................................................................................................. 273
+TPM2_PolicyCpHash .................................................................................................................. 276
+TPM2_PolicyNameHash ............................................................................................................. 280
+TPM2_PolicyDuplicationSelect ................................................................................................... 283
+TPM2_PolicyAuthorize ............................................................................................................... 287
+TPM2_PolicyAuthValue .............................................................................................................. 291
+TPM2_PolicyPassword ............................................................................................................... 294
+TPM2_PolicyGetDigest ............................................................................................................... 297
+TPM2_PolicyNvWritten ............................................................................................................... 300
+
+Hierarchy Commands........................................................................................................................ 304
+
+26.1
+26.2
+26.3
+
+TPM2_CreatePrimary ................................................................................................................. 304
+TPM2_HierarchyControl ............................................................................................................. 308
+TPM2_SetPrimaryPolicy ............................................................................................................. 312
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page v
+October 31, 2013
+
+ Part 3: Commands
+26.4
+26.5
+26.6
+26.7
+26.8
+27
+
+TPM2_ReadClock ....................................................................................................................... 372
+TPM2_ClockSet .......................................................................................................................... 375
+TPM2_ClockRateAdjust .............................................................................................................. 378
+
+Capability Commands ....................................................................................................................... 381
+
+32.1
+32.2
+32.3
+33
+
+Introduction ................................................................................................................................. 354
+TPM2_ContextSave .................................................................................................................... 354
+TPM2_ContextLoad .................................................................................................................... 359
+TPM2_FlushContext ................................................................................................................... 364
+TPM2_EvictControl ..................................................................................................................... 367
+
+Clocks and Timers............................................................................................................................. 372
+
+31.1
+31.2
+31.3
+32
+
+Introduction ................................................................................................................................. 343
+TPM2_FieldUpgradeStart ........................................................................................................... 345
+TPM2_FieldUpgradeData ........................................................................................................... 348
+TPM2_FirmwareRead ................................................................................................................. 351
+
+Context Management ........................................................................................................................ 354
+
+30.1
+30.2
+30.3
+30.4
+30.5
+31
+
+Introduction ................................................................................................................................. 337
+TPM2_PP_Commands ............................................................................................................... 337
+TPM2_SetAlgorithmSet .............................................................................................................. 340
+
+Field Upgrade .................................................................................................................................... 343
+
+29.1
+29.2
+29.3
+29.4
+30
+
+Introduction ................................................................................................................................. 331
+TPM2_DictionaryAttackLockReset ............................................................................................. 331
+TPM2_DictionaryAttackParameters............................................................................................ 334
+
+Miscellaneous Management Functions ............................................................................................. 337
+
+28.1
+28.2
+28.3
+29
+
+TPM2_ChangePPS .................................................................................................................... 315
+TPM2_ChangeEPS .................................................................................................................... 318
+TPM2_Clear ................................................................................................................................ 321
+TPM2_ClearControl .................................................................................................................... 325
+TPM2_HierarchyChangeAuth ..................................................................................................... 328
+
+Dictionary Attack Functions ............................................................................................................... 331
+
+27.1
+27.2
+27.3
+28
+
+Trusted Platform Module Library
+
+Introduction ................................................................................................................................. 381
+TPM2_GetCapability ................................................................................................................... 381
+TPM2_TestParms ....................................................................................................................... 389
+
+Non-volatile Storage .......................................................................................................................... 392
+
+33.1
+33.2
+33.3
+33.4
+33.5
+33.6
+33.7
+33.8
+33.9
+33.10
+33.11
+
+Introduction ................................................................................................................................. 392
+NV Counters ............................................................................................................................... 393
+TPM2_NV_DefineSpace ............................................................................................................. 394
+TPM2_NV_UndefineSpace ......................................................................................................... 400
+TPM2_NV_UndefineSpaceSpecial ............................................................................................. 403
+TPM2_NV_ReadPublic ............................................................................................................... 406
+TPM2_NV_Write ......................................................................................................................... 409
+TPM2_NV_Increment ................................................................................................................. 413
+TPM2_NV_Extend ...................................................................................................................... 417
+TPM2_NV_SetBits ...................................................................................................................... 421
+TPM2_NV_WriteLock ................................................................................................................. 425
+
+Page vi
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+33.12
+33.13
+33.14
+33.15
+33.16
+
+Part 3: Commands
+
+TPM2_NV_GlobalWriteLock ....................................................................................................... 429
+TPM2_NV_Read ......................................................................................................................... 432
+TPM2_NV_ReadLock ................................................................................................................. 435
+TPM2_NV_ChangeAuth ............................................................................................................. 438
+TPM2_NV_Certify ....................................................................................................................... 441
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page vii
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Tables
+Table 1 — Command Modifiers and Decoration ........................................................................................... 2
+Table 2 — Separators ................................................................................................................................... 3
+Table 3 — Unmarshaling Errors ................................................................................................................. 10
+Table 4 — Command-Independent Response Codes ................................................................................ 13
+Table 5 — TPM2_Startup Command .......................................................................................................... 21
+Table 6 — TPM2_Startup Response .......................................................................................................... 21
+Table 7 — TPM2_Shutdown Command ..................................................................................................... 25
+Table 8 — TPM2_Shutdown Response ...................................................................................................... 25
+Table 9 — TPM2_SelfTest Command ........................................................................................................ 30
+Table 10 — TPM2_SelfTest Response ...................................................................................................... 30
+Table 11 — TPM2_IncrementalSelfTest Command ................................................................................... 33
+Table 12 — TPM2_IncrementalSelfTest Response ................................................................................... 33
+Table 13 — TPM2_GetTestResult Command ............................................................................................ 36
+Table 14 — TPM2_GetTestResult Response............................................................................................. 36
+Table 15 — TPM2_StartAuthSession Command ....................................................................................... 40
+Table 16 — TPM2_StartAuthSession Response ........................................................................................ 40
+Table 17 — TPM2_PolicyRestart Command .............................................................................................. 44
+Table 18 — TPM2_PolicyRestart Response .............................................................................................. 44
+Table 19 — TPM2_Create Command ........................................................................................................ 48
+Table 20 — TPM2_Create Response ......................................................................................................... 48
+Table 21 — TPM2_Load Command ........................................................................................................... 52
+Table 22 — TPM2_Load Response ............................................................................................................ 52
+Table 23 — TPM2_LoadExternal Command .............................................................................................. 57
+Table 24 — TPM2_LoadExternal Response .............................................................................................. 57
+Table 25 — TPM2_ReadPublic Command ................................................................................................. 61
+Table 26 — TPM2_ReadPublic Response ................................................................................................. 61
+Table 27 — TPM2_ActivateCredential Command ...................................................................................... 64
+Table 28 — TPM2_ActivateCredential Response ...................................................................................... 64
+Table 29 — TPM2_MakeCredential Command .......................................................................................... 68
+Table 30 — TPM2_MakeCredential Response .......................................................................................... 68
+Table 31 — TPM2_Unseal Command ........................................................................................................ 71
+Table 32 — TPM2_Unseal Response ........................................................................................................ 71
+Table 33 — TPM2_ObjectChangeAuth Command ..................................................................................... 74
+Table 34 — TPM2_ObjectChangeAuth Response ..................................................................................... 74
+Table 35 — TPM2_Duplicate Command .................................................................................................... 78
+Table 36 — TPM2_Duplicate Response ..................................................................................................... 78
+Table 37 — TPM2_Rewrap Command ....................................................................................................... 82
+Table 38 — TPM2_Rewrap Response ....................................................................................................... 82
+Page viii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 39 — TPM2_Import Command ......................................................................................................... 88
+Table 40 — TPM2_Import Response ......................................................................................................... 88
+Table 41 — Padding Scheme Selection ..................................................................................................... 92
+Table 42 — Message Size Limits Based on Padding ................................................................................. 93
+Table 43 — TPM2_RSA_Encrypt Command.............................................................................................. 94
+Table 44 — TPM2_RSA_Encrypt Response .............................................................................................. 94
+Table 45 — TPM2_RSA_Decrypt Command ............................................................................................. 98
+Table 46 — TPM2_RSA_Decrypt Response .............................................................................................. 98
+Table 47 — TPM2_ECDH_KeyGen Command ........................................................................................ 102
+Table 48 — TPM2_ECDH_KeyGen Response ........................................................................................ 102
+Table 49 — TPM2_ECDH_ZGen Command ............................................................................................ 105
+Table 50 — TPM2_ECDH_ZGen Response ............................................................................................ 105
+Table 51 — TPM2_ECC_Parameters Command ..................................................................................... 107
+Table 52 — TPM2_ECC_Parameters Response ..................................................................................... 107
+Table 53 — TPM2_ZGen_2Phase Command .......................................................................................... 110
+Table 54 — TPM2_ZGen_2Phase Response .......................................................................................... 110
+Table 55 — Symmetric Chaining Process ................................................................................................ 114
+Table 56 — TPM2_EncryptDecrypt Command......................................................................................... 116
+Table 57 — TPM2_EncryptDecrypt Response ......................................................................................... 116
+Table 58 — TPM2_Hash Command ......................................................................................................... 120
+Table 59 — TPM2_Hash Response ......................................................................................................... 120
+Table 60 — TPM2_HMAC Command ....................................................................................................... 123
+Table 61 — TPM2_HMAC Response ....................................................................................................... 123
+Table 62 — TPM2_GetRandom Command .............................................................................................. 127
+Table 63 — TPM2_GetRandom Response .............................................................................................. 127
+Table 64 — TPM2_StirRandom Command .............................................................................................. 130
+Table 65 — TPM2_StirRandom Response ............................................................................................... 130
+Table 66 — Hash Selection Matrix ........................................................................................................... 132
+Table 67 — TPM2_HMAC_Start Command ............................................................................................. 133
+Table 68 — TPM2_HMAC_Start Response ............................................................................................. 133
+Table 69 — TPM2_HashSequenceStart Command ................................................................................. 137
+Table 70 — TPM2_HashSequenceStart Response ................................................................................. 137
+Table 71 — TPM2_SequenceUpdate Command ..................................................................................... 140
+Table 72 — TPM2_SequenceUpdate Response ...................................................................................... 140
+Table 73 — TPM2_SequenceComplete Command ................................................................................. 144
+Table 74 — TPM2_SequenceComplete Response .................................................................................. 144
+Table 75 — TPM2_EventSequenceComplete Command ........................................................................ 148
+Table 76 — TPM2_EventSequenceComplete Response ......................................................................... 148
+Table 77 — TPM2_Certify Command ....................................................................................................... 154
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page ix
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Table 78 — TPM2_Certify Response ....................................................................................................... 154
+Table 79 — TPM2_CertifyCreation Command ......................................................................................... 158
+Table 80 — TPM2_CertifyCreation Response .......................................................................................... 158
+Table 81 — TPM2_Quote Command ....................................................................................................... 162
+Table 82 — TPM2_Quote Response ........................................................................................................ 162
+Table 83 — TPM2_GetSessionAuditDigest Command ............................................................................ 166
+Table 84 — TPM2_GetSessionAuditDigest Response ............................................................................ 166
+Table 85 — TPM2_GetCommandAuditDigest Command ........................................................................ 170
+Table 86 — TPM2_GetCommandAuditDigest Response ......................................................................... 170
+Table 87 — TPM2_GetTime Command ................................................................................................... 174
+Table 88 — TPM2_GetTime Response .................................................................................................... 174
+Table 89 — TPM2_Commit Command ..................................................................................................... 180
+Table 90 — TPM2_Commit Response ..................................................................................................... 180
+Table 91 — TPM2_EC_Ephemeral Command ......................................................................................... 185
+Table 92 — TPM2_EC_Ephemeral Response ......................................................................................... 185
+Table 93 — TPM2_VerifySignature Command......................................................................................... 188
+Table 94 — TPM2_VerifySignature Response ......................................................................................... 188
+Table 95 — TPM2_Sign Command .......................................................................................................... 192
+Table 96 — TPM2_Sign Response .......................................................................................................... 192
+Table 97 — TPM2_SetCommandCodeAuditStatus Command ................................................................ 197
+Table 98 — TPM2_SetCommandCodeAuditStatus Response ................................................................ 197
+Table 99 — TPM2_PCR_Extend Command ............................................................................................ 202
+Table 100 — TPM2_PCR_Extend Response ........................................................................................... 202
+Table 101 — TPM2_PCR_Event Command ............................................................................................ 205
+Table 102 — TPM2_PCR_Event Response ............................................................................................. 205
+Table 103 — TPM2_PCR_Read Command ............................................................................................. 208
+Table 104 — TPM2_PCR_Read Response ............................................................................................. 208
+Table 105 — TPM2_PCR_Allocate Command ......................................................................................... 211
+Table 106 — TPM2_PCR_Allocate Response ......................................................................................... 211
+Table 107 — TPM2_PCR_SetAuthPolicy Command ............................................................................... 214
+Table 108 — TPM2_PCR_SetAuthPolicy Response ............................................................................... 214
+Table 109 — TPM2_PCR_SetAuthValue Command ............................................................................... 217
+Table 110 — TPM2_PCR_SetAuthValue Response ................................................................................ 217
+Table 111 — TPM2_PCR_Reset Command ............................................................................................ 220
+Table 112 — TPM2_PCR_Reset Response ............................................................................................. 220
+Table 113 — TPM2_PolicySigned Command .......................................................................................... 236
+Table 114 — TPM2_PolicySigned Response ........................................................................................... 236
+Table 115 — TPM2_PolicySecret Command ........................................................................................... 241
+Table 116 — TPM2_PolicySecret Response ............................................................................................ 241
+Page x
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 117 — TPM2_PolicyTicket Command ............................................................................................ 245
+Table 118 — TPM2_PolicyTicket Response ............................................................................................ 245
+Table 119 — TPM2_PolicyOR Command ................................................................................................ 249
+Table 120 — TPM2_PolicyOR Response ................................................................................................. 249
+Table 121 — TPM2_PolicyPCR Command .............................................................................................. 253
+Table 122 — TPM2_PolicyPCR Response .............................................................................................. 253
+Table 123 — TPM2_PolicyLocality Command ......................................................................................... 257
+Table 124 — TPM2_PolicyLocality Response .......................................................................................... 257
+Table 125 — TPM2_PolicyNV Command ................................................................................................. 261
+Table 126 — TPM2_PolicyNV Response ................................................................................................. 261
+Table 127 — TPM2_PolicyCounterTimer Command ............................................................................... 266
+Table 128 — TPM2_PolicyCounterTimer Response ................................................................................ 266
+Table 129 — TPM2_PolicyCommandCode Command ............................................................................ 271
+Table 130 — TPM2_PolicyCommandCode Response ............................................................................. 271
+Table 131 — TPM2_PolicyPhysicalPresence Command ......................................................................... 274
+Table 132 — TPM2_PolicyPhysicalPresence Response ......................................................................... 274
+Table 133 — TPM2_PolicyCpHash Command......................................................................................... 277
+Table 134 — TPM2_PolicyCpHash Response ......................................................................................... 277
+Table 135 — TPM2_PolicyNameHash Command.................................................................................... 281
+Table 136 — TPM2_PolicyNameHash Response .................................................................................... 281
+Table 137 — TPM2_PolicyDuplicationSelect Command .......................................................................... 284
+Table 138 — TPM2_PolicyDuplicationSelect Response .......................................................................... 284
+Table 139 — TPM2_PolicyAuthorize Command ...................................................................................... 288
+Table 140 — TPM2_PolicyAuthorize Response ....................................................................................... 288
+Table 141 — TPM2_PolicyAuthValue Command ..................................................................................... 292
+Table 142 — TPM2_PolicyAuthValue Response ..................................................................................... 292
+Table 143 — TPM2_PolicyPassword Command ...................................................................................... 295
+Table 144 — TPM2_PolicyPassword Response ...................................................................................... 295
+Table 145 — TPM2_PolicyGetDigest Command...................................................................................... 298
+Table 146 — TPM2_PolicyGetDigest Response ...................................................................................... 298
+Table 133 — TPM2_PolicyNvWritten Command ...................................................................................... 301
+Table 134 — TPM2_PolicyNvWritten Response ...................................................................................... 301
+Table 147 — TPM2_CreatePrimary Command ........................................................................................ 305
+Table 148 — TPM2_CreatePrimary Response ........................................................................................ 305
+Table 149 — TPM2_HierarchyControl Command .................................................................................... 309
+Table 150 — TPM2_HierarchyControl Response .................................................................................... 309
+Table 151 — TPM2_SetPrimaryPolicy Command .................................................................................... 313
+Table 152 — TPM2_SetPrimaryPolicy Response .................................................................................... 313
+Table 153 — TPM2_ChangePPS Command ........................................................................................... 316
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xi
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Table 154 — TPM2_ChangePPS Response ............................................................................................ 316
+Table 155 — TPM2_ChangeEPS Command ........................................................................................... 319
+Table 156 — TPM2_ChangeEPS Response ............................................................................................ 319
+Table 157 — TPM2_Clear Command ....................................................................................................... 322
+Table 158 — TPM2_Clear Response ....................................................................................................... 322
+Table 159 — TPM2_ClearControl Command ........................................................................................... 326
+Table 160 — TPM2_ClearControl Response ........................................................................................... 326
+Table 161 — TPM2_HierarchyChangeAuth Command ............................................................................ 329
+Table 162 — TPM2_HierarchyChangeAuth Response ............................................................................ 329
+Table 163 — TPM2_DictionaryAttackLockReset Command .................................................................... 332
+Table 164 — TPM2_DictionaryAttackLockReset Response .................................................................... 332
+Table 165 — TPM2_DictionaryAttackParameters Command .................................................................. 335
+Table 166 — TPM2_DictionaryAttackParameters Response ................................................................... 335
+Table 167 — TPM2_PP_Commands Command ...................................................................................... 338
+Table 168 — TPM2_PP_Commands Response ...................................................................................... 338
+Table 169 — TPM2_SetAlgorithmSet Command ..................................................................................... 341
+Table 170 — TPM2_SetAlgorithmSet Response...................................................................................... 341
+Table 171 — TPM2_FieldUpgradeStart Command .................................................................................. 346
+Table 172 — TPM2_FieldUpgradeStart Response .................................................................................. 346
+Table 173 — TPM2_FieldUpgradeData Command .................................................................................. 349
+Table 174 — TPM2_FieldUpgradeData Response .................................................................................. 349
+Table 175 — TPM2_FirmwareRead Command........................................................................................ 352
+Table 176 — TPM2_FirmwareRead Response ........................................................................................ 352
+Table 177 — TPM2_ContextSave Command........................................................................................... 355
+Table 178 — TPM2_ContextSave Response ........................................................................................... 355
+Table 179 — TPM2_ContextLoad Command ........................................................................................... 360
+Table 180 — TPM2_ContextLoad Response ........................................................................................... 360
+Table 181 — TPM2_FlushContext Command .......................................................................................... 365
+Table 182 — TPM2_FlushContext Response .......................................................................................... 365
+Table 183 — TPM2_EvictControl Command ............................................................................................ 369
+Table 184 — TPM2_EvictControl Response ............................................................................................ 369
+Table 185 — TPM2_ReadClock Command.............................................................................................. 373
+Table 186 — TPM2_ReadClock Response .............................................................................................. 373
+Table 187 — TPM2_ClockSet Command ................................................................................................. 376
+Table 188 — TPM2_ClockSet Response ................................................................................................. 376
+Table 189 — TPM2_ClockRateAdjust Command..................................................................................... 379
+Table 190 — TPM2_ClockRateAdjust Response ..................................................................................... 379
+Table 191 — TPM2_GetCapability Command.......................................................................................... 385
+Table 192 — TPM2_GetCapability Response .......................................................................................... 385
+Page xii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 193 — TPM2_TestParms Command .............................................................................................. 390
+Table 194 — TPM2_TestParms Response .............................................................................................. 390
+Table 195 — TPM2_NV_DefineSpace Command ................................................................................... 396
+Table 196 — TPM2_NV_DefineSpace Response .................................................................................... 396
+Table 197 — TPM2_NV_UndefineSpace Command ............................................................................... 401
+Table 198 — TPM2_NV_UndefineSpace Response ................................................................................ 401
+Table 199 — TPM2_NV_UndefineSpaceSpecial Command .................................................................... 404
+Table 200 — TPM2_NV_UndefineSpaceSpecial Response .................................................................... 404
+Table 201 — TPM2_NV_ReadPublic Command ...................................................................................... 407
+Table 202 — TPM2_NV_ReadPublic Response ...................................................................................... 407
+Table 203 — TPM2_NV_Write Command ................................................................................................ 410
+Table 204 — TPM2_NV_Write Response ................................................................................................ 410
+Table 205 — TPM2_NV_Increment Command ........................................................................................ 414
+Table 206 — TPM2_NV_Increment Response......................................................................................... 414
+Table 207 — TPM2_NV_Extend Command ............................................................................................. 418
+Table 208 — TPM2_NV_Extend Response ............................................................................................. 418
+Table 209 — TPM2_NV_SetBits Command ............................................................................................. 422
+Table 210 — TPM2_NV_SetBits Response ............................................................................................. 422
+Table 211 — TPM2_NV_WriteLock Command ........................................................................................ 426
+Table 212 — TPM2_NV_WriteLock Response......................................................................................... 426
+Table 213 — TPM2_NV_GlobalWriteLock Command .............................................................................. 430
+Table 214 — TPM2_NV_GlobalWriteLock Response .............................................................................. 430
+Table 215 — TPM2_NV_Read Command................................................................................................ 433
+Table 216 — TPM2_NV_Read Response ................................................................................................ 433
+Table 217 — TPM2_NV_ReadLock Command ........................................................................................ 436
+Table 218 — TPM2_NV_ReadLock Response ........................................................................................ 436
+Table 219 — TPM2_NV_ChangeAuth Command .................................................................................... 439
+Table 220 — TPM2_NV_ChangeAuth Response .................................................................................... 439
+Table 221 — TPM2_NV_Certify Command .............................................................................................. 442
+Table 222 — TPM2_NV_Certify Response .............................................................................................. 442
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xiii
+October 31, 2013
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Trusted Platform Module Library
+Part 3: Commands
+1
+
+Scope
+
+This part 3 of the Trusted Module Library specification contains the definitions of the TPM commands.
+These commands make use of the constants, flags, structure, and union definitions defined in part 2:
+Structures.
+The detailed description of the operation of the commands is written in the C language with extensive
+comments. The behavior of the C code in this part 3 is normative but does not fully describe the behavior
+of a TPM. The combination of this part 3 and part 4: Supporting Routines is sufficient to fully describe the
+required behavior of a TPM.
+The code in parts 3 and 4 is written to define the behavior of a compliant TPM. In some cases (e.g.,
+firmware update), it is not possible to provide a compliant implementation. In those cases, any
+implementation provided by the vendor that meets the general description of the function provided in part
+3 would be compliant.
+The code in parts 3 and 4 is not written to meet any particular level of conformance nor does this
+specification require that a TPM meet any particular level of conformance.
+2
+
+Terms and Definitions
+
+For the purposes of this document, the terms and definitions given in part 1 of this specification apply.
+3
+
+Symbols and abbreviated terms
+
+For the purposes of this document, the symbols and abbreviated terms given in part 1 apply.
+4
+
+Notation
+
+4.1 Introduction
+In addition to the notation in this clause, the “Notations” clause in Part 1 of this specification is applicable
+to this Part 3.
+Command and response tables used various decorations to indicate the fields of the command and the
+allowed types. These decorations are described in this clause.
+4.2
+
+Table Decorations
+
+The symbols and terms in the Notation column of Table 1 are used in the tables for the command
+schematics. These values indicate various qualifiers for the parameters or descriptions with which they
+are associated.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 1
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+Table 1 — Command Modifiers and Decoration
+
+Notation
+
+Meaning
+
++
+
+A Type decoration – When appended to a value in the Type column of a command, this symbol
+indicates that the parameter is allowed to use the “null” value of the data type (see "Conditional
+Types" in Part 2). The null value is usually TPM_RH_NULL for a handle or TPM_ALG_NULL for
+an algorithm selector.
+
+@
+
+A Name decoration – When this symbol precedes a handle parameter in the “Name” column, it
+indicates that an authorization session is required for use of the entity associated with the handle.
+If a handle does not have this symbol, then an authorization session is not allowed.
+
++PP
+
+A Description modifier – This modifier may follow TPM_RH_PLATFORM in the “Description”
+column to indicate that Physical Presence is required when platformAuth/platformPolicy is
+provided.
+
++{PP}
+
+A Description modifier – This modifier may follow TPM_RH_PLATFORM to indicate that Physical
+Presence may be required when platformAuth/platformPolicy is provided. The commands with this
+notation may be in the setList or clearList of TPM2_PP_Commands().
+
+{NV}
+
+A Description modifier – This modifier may follow the commandCode in the “Description” column
+to indicate that the command may result in an update of NV memory and be subject to rate
+throttling by the TPM. If the command code does not have this notation, then a write to NV
+memory does not occur as part of the command actions.
+NOTE Any command that uses authorization may cause a write to NV if there is an authorization
+failure. A TPM may use the occasion of command execution to update the NV
+copy of clock.
+
+{F}
+
+A Description modifier – This modifier indicates that the “flushed” attribute will be SET in the
+TPMA_CC for the command. The modifier may follow the commandCode in the “Description”
+column to indicate that any transient handle context used by the command will be flushed from the
+TPM when the command completes. This may be combined with the {NV} modifier but not with the
+{E} modifier.
+EXAMPLE 1
+
+{E}
+
+{NV F}
+
+EXAMPLE 2
+
+TPM2_SequenceComplete() will flush the context associated with the sequenceHandle.
+
+A Description modifier – This modifier indicates that the “extensive” attribute will be SET in the
+TPMA_CC for the command. This modifier may follow the commandCode in the “Description”
+column to indicate that the command may flush many objects and re-enumeration of the loaded
+context likely will be required. This may be combined with the {NV} modifier but not with the {F}
+modifier.
+EXAMPLE 1
+
+Auth Index:
+
+{NV E}
+
+EXAMPLE 2
+
+TPM2_Clear() will flush all contexts associated with the Storage hierarchy and the
+Endorsement hierarchy.
+
+A Description modifier – When a handle has a “@” decoration, the “Description” column will
+contain an “Auth Index:” entry for the handle. This entry indicates the number of the authorization
+session. The authorization sessions associated with handles will occur in the session area in the
+order of the handles with the “@” modifier. Sessions used only for encryption/decryption or only for
+audit will follow the handles used for authorization.
+
+Page 2
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Notation
+
+Meaning
+
+Auth Role:
+
+A Description modifier – This will be in the “Description” column of a handle with the “@”
+decoration. It may have a value of USER, ADMIN or DUP. If the handle has the Auth Role of
+USER and the handle is an Object, the type of authorization is determined by the setting of
+userWithAuth in the Object's attributes. If the Auth Role is ADMIN and the handle is an Object, the
+type of authorization is determined by the setting of adminWithPolicy in the Object's attributes. If
+the DUP role is selected, authorization may only be with a policy session (DUP role only applies to
+Objects). When either ADMIN or DUP role is selected, a policy command that selects the
+command being authorized is required to be part of the policy.
+EXAMPLE
+
+TPM2_Certify requires the ADMIN role for the first handle (objectHandle). The policy authorization
+for objectHandle is required to contain TPM2_PolicyCommandCode(commandCode ==
+TPM_CC_Certify). This sets the state of the policy so that it can be used for ADMIN role
+authorization in TPM2_Certify().
+
+If the handle references an NV Index, then the allowed authorizations are determined by the
+settings of the attributes of the NV Index as described in Part 2, "TPMA_NV (NV Index Attributes)."
+
+4.3
+
+Handle and Parameter Demarcation
+
+The demarcations between the header, handle, and parameter parts are indicated by:
+Table 2 — Separators
+Separator
+
+Meaning
+the values immediately following are in the handle area
+the values immediately following are in the parameter area
+
+4.4
+
+AuthorizationSize and ParameterSize
+
+Authorization sessions are not shown in the command or response schematics. When the tag of a
+command or response is TPM_ST_SESSIONS, then a 32-bit value will be present in the
+command/response buffer to indicate the size of the authorization field or the parameter field. This value
+shall immediately follow the handle area (which may contain no handles). For a command, this value
+(authorizationSize) indicates the size of the Authorization Area and shall have a value of 9 or more. For a
+response, this value (parameterSize) indicates the size of the parameter area and may have a value of
+zero.
+If the authorizationSize field is present in the command, parameterSize will be present in the response,
+but only if the responseCode is TPM_RC_SUCCESS.
+When the command tag is TPM_ST_NO_SESSIONS, no authorizations are present and no
+authorizationSize field is required and shall not be present.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 3
+October 31, 2013
+
+ Part 3: Commands
+
+5
+
+Trusted Platform Module Library
+
+Normative References
+
+The “Normative References” clause in Part 1 of this specification is applicable to this Part 3.
+6
+
+Symbols and Abbreviated Terms
+
+The “Symbols and Abbreviated Terms” clause in Part 1 of this specification is applicable to this Part 3.
+
+7
+7.1
+
+Command Processing
+Introduction
+
+This clause defines the command validations that are required of any implementation and the response
+code returned if the indicated check fails. Unless stated otherwise, the order of the checks is not
+normative and different TPM may give different responses when a command has multiple errors.
+In the description below, some statements that describe a check may be followed by a response code in
+parentheses. This is the normative response code should the indicated check fail. A normative response
+code may also be included in the statement.
+7.2
+
+Command Header Validation
+
+Before a TPM may begin the actions associated with a command, a set of command format and
+consistency checks shall be performed. These checks are listed below and should be performed in the
+indicated order.
+a) The TPM shall successfully unmarshal a TPMI_ST_COMMAND_TAG and verify that it is either
+TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS (TPM_RC_BAD_TAG).
+b) The TPM shall successfully unmarshal a UINT32 as the commandSize. If the TPM has an interface
+buffer that is loaded by some hardware process, the number of octets in the input buffer for the
+command reported by the hardware process shall exactly match the value in commandSize
+(TPM_RC_COMMAND_SIZE).
+NOTE
+
+A TPM may have direct access to system memory and unmarshal directly from that memory.
+
+c) The TPM shall successfully unmarshal a TPM_CC and verify that the command is implemented
+(TPM_RC_COMMAND_CODE).
+7.3
+
+Mode Checks
+
+The following mode checks shall be performed in the order listed:
+
+Page 4
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+a) If the TPM is in Failure mode, then the commandCode is TPM_CC_GetTestResult or
+TPM_CC_GetCapability (TPM_RC_FAILURE) and the command tag is TPM_ST_NO_SESSIONS
+(TPM_RC_FAILURE).
+NOTE 1
+
+In Failure mode, the TPM has no cryptographic capability and proc essing of sessions is not
+supported.
+
+b) The TPM is in Field Upgrade mode (FUM), the commandCode is TPM_CC_FieldUpgradeData
+(TPM_RC_UPGRADE).
+c) If the TPM has not been initialized (TPM2_Startup()), then the commandCode is TPM_CC_Startup
+(TPM_RC_INITIALIZE).
+NOTE 2
+
+The TPM may enter Failure mode during _TPM_Init processing, before TPM2_Startup(). Since
+the platform firmware cannot know that the TPM is in Failure mode without accessing it, and
+since the first command is required to be TPM2_Startup(), the expected sequence will be that
+platform firmware (the CRTM) will issue TPM2_Startup() and receive TPM_RC_FAILURE
+indicating that the TPM is in Failure mode.
+There may be failures where a TPM cannot record that it received TPM2_Startup(). In those
+cases, a TPM in failure mode may process TPM2_GetTestResult(), TPM2_GetCapability(), or
+the field upgrade commands. As a side effect, that TPM may process TPM2_GetTestResult(),
+TPM2_GetCapability() or the field upgrade commands before TPM2_Startup().
+This is a corner case exception to the rule that TPM2_Startup() must be the first command.
+
+The mode checks may be performed before or after the command header validation.
+7.4 Handle Area Validation
+After successfully unmarshaling and validating the command header, the TPM shall perform the following
+checks on the handles and sessions. These checks may be performed in any order.
+a) The TPM shall successfully unmarshal the number of handles required by the command and validate
+that the value of the handle is consistent with the command syntax. If not, the TPM shall return
+TPM_RC_VALUE.
+NOTE 1
+
+The TPM may unmarshal a handle and validate that it references an entity on the TPM before
+unmarshaling a subsequent handle.
+
+NOTE 2
+
+If the submitted command contains fewer handles than required by the syntax of the command,
+the TPM may continue to read into the next area and attempt to interpret the data as a handle.
+
+b) For all handles in the handle area of the command, the TPM will validate that the referenced entity is
+present in the TPM.
+1) If the handle references a transient object, the handle shall reference a loaded object
+(TPM_RC_REFERENCE_H0 + N where N is the number of the handle in the command).
+NOTE 3
+
+If the hierarchy for a transient object is disabled, then the transient objects will be flushe d so this
+check will fail.
+
+2) If the handle references a persistent object, then
+i)
+
+the handle shall reference a persistent object that is currently in TPM non-volatile memory
+(TPM_RC_HANDLE);
+
+ii)
+
+the hierarchy associated with the object is not disabled (TPM_RC_HIERARCHY); and
+
+iii) if the TPM implementation moves a persistent object to RAM for command processing then
+sufficient RAM space is available (TPM_RC_OBJECT_MEMORY).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 5
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+3) If the handle references an NV Index, then
+i)
+
+an Index exists that corresponds to the handle (TPM_RC_HANDLE); and
+
+ii)
+
+the hierarchy associated with the existing NV Index is not disabled (TPM_RC_HANDLE).
+
+iii) the hierarchy associated
+(TPM_RC_HIERARCHY)
+
+with
+
+an
+
+NV
+
+index
+
+being
+
+defined
+
+is
+
+not
+
+disabled
+
+4) If the handle references a session, then the session context shall be present in TPM memory
+(TPM_RC_REFERENCE_S0 + N).
+5) If the handle references a primary seed for a hierarchy (TPM_RH_ENDORSEMENT,
+TPM_RH_OWNER, or TPM_RH_PLATFORM) then the enable for the hierarchy is SET
+(TPM_RC_HIERARCHY).
+6) If the handle references a PCR, then the value is within the range of PCR supported by the TPM
+(TPM_RC_VALUE)
+NOTE 4
+
+7.5
+
+In the reference implementation, this TPM_RC_VALUE is returned by the unmarshaling code for
+a TPMI_DH_PCR.
+
+Session Area Validation
+
+a) If the tag is TPM_ST_SESSIONS and the command is a context management command
+(TPM2_ContextSave(), TPM2_ContextLoad(), or TPM2_FlushContext()) the TPM will return
+TPM_RC_AUTH_CONTEXT.
+b) If the tag is TPM_ST_SESSIONS, the TPM will attempt to unmarshal an authorizationSize and return
+TPM_RC_AUTHSIZE if the value is not within an acceptable range.
+1) The minimum value is (sizeof(TPM_HANDLE) + sizeof(UINT16) + sizeof(TPMA_SESSION) +
+sizeof(UINT16)).
+2) The maximum value of authorizationSize is equal to commandSize – (sizeof(TPM_ST) +
+sizeof(UINT32) + sizeof(TPM_CC) + (N * sizeof(TPM_HANDLE)) + sizeof(UINT32)) where N is
+the number of handles associated with the commandCode and may be zero.
+NOTE 1
+
+(sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_CC)) is the size of a command header. The
+last UINT32 contains the authorizationSize octets, which are not counted as being in the
+authorization session area.
+
+c) The TPM will unmarshal the authorization sessions and perform the following validations:
+1) If the session handle is not a handle for an HMAC session, a handle for a policy session, or,
+TPM_RS_PW then the TPM shall return TPM_RC_HANDLE.
+2) If the session is not loaded, the TPM will return the warning TPM_RC_REFERENCE_S0 + N
+where N is the number of the session. The first session is session zero, N = 0.
+NOTE 2
+
+If the HMAC and policy session contexts use the same memory, the type of the context must
+match the type of the handle.
+
+3) If the maximum allowed number of sessions have been unmarshaled and fewer octets than
+indicated in authorizationSize were unmarshaled (that is, authorizationSize is too large), the TPM
+shall return TPM_RC_AUTHSIZE.
+
+Page 6
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+4) The consistency of the authorization session attributes is checked.
+i)
+
+An authorization session is present for each of the handles with the “@” decoration
+(TPM_RC_AUTH_MISSING).
+
+ii)
+
+Only one session is allowed for:
+(a) session auditing (TPM_RC_ATTRIBUTES) – this session may be used for encrypt or
+decrypt but may not be a session that is also used for authorization;
+(b) decrypting a command parameter (TPM_RC_ATTRIBUTES) – this may be any of the
+authorization sessions, or the audit session, or a session may be added for the single
+purpose of decrypting a command parameter, as long as the total number of sessions
+does not exceed three; and
+(c) encrypting a response parameter (TPM_RC_ATTRIBUTES) – this may be any of the
+authorization sessions, or the audit session if present, ora session may be added for the
+single purpose of encrypting a response parameter, as long as the total number of
+sessions does not exceed three.
+NOTE 3
+
+7.6
+
+A session used for decrypting a command parameter may also be used for
+encrypting a response parameter.
+
+Authorization Checks
+
+After unmarshaling and validating the handles and the consistency of the authorization sessions, the
+authorizations shall be checked. Authorization checks only apply to handles if the handle in the command
+schematic has the “@” decoration.
+a) The public and sensitive portions
+(TPM_RC_AUTH_UNAVAILABLE).
+
+of
+
+the
+
+object
+
+shall
+
+be
+
+present
+
+on
+
+the
+
+TPM
+
+b) If the associated handle is TPM_RH_PLATFORM, and the command requires confirmation with
+physical presence, then physical presence is asserted (TPM_RC_PP).
+c) If the object or NV Index is subject to DA protection, and the authorization is with an HMAC or
+password, then the TPM is not in lockout (TPM_RC_LOCKOUT).
+NOTE 1
+
+An object is subject to DA protection if its noDA attribute is CLEAR. An NV Index is subject to
+DA protection if its TPMA_NV_NO_DA attribute is CLEAR.
+
+NOTE 2
+
+An HMAC or password is required in a policy
+TPM2_PolicyAuthValue() or TPM2_PolicyPassword().
+
+session
+
+when
+
+the
+
+policy
+
+contains
+
+d) If the command requires a handle to have DUP role authorization, then the associated authorization
+session is a policy session (TPM_RC_POLICY_FAIL).
+e) If the command requires a handle to have ADMIN role authorization:
+1) If the entity being authorized is an object and its adminWithPolicy attribute is SET, then the
+authorization session is a policy session (TPM_RC_POLICY_FAIL).
+NOTE 3
+
+If adminWithPolicy is CLEAR, then any type of authorization session is allowed .
+
+2) If the entity being authorized is an NV Index, then the associated authorization session is a policy
+session.
+NOTE 4
+
+The only commands that are currently defined that required use of ADMIN role authorization are
+commands that operate on objects and NV Indices.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 7
+October 31, 2013
+
+ Part 3: Commands
+f)
+
+Trusted Platform Module Library
+
+If the command requires a handle to have USER role authorization:
+1) If the entity being authorized is an object and its userWithAuth attribute is CLEAR, then the
+associated authorization session is a policy session (TPM_RC_POLICY_FAIL).
+2) If the entity being authorized is an NV Index;
+i)
+
+if the authorization session is a policy session;
+(a) the TPMA_NV_POLICYWRITE attribute of the NV Index is SET if the command modifies
+the NV Index data (TPM_RC_AUTH_UNAVAILABLE);
+(b) the TPMA_NV_POLICYREAD attribute of the NV Index is SET if the command reads the
+NV Index data (TPM_RC_AUTH_UNAVAILABLE);
+
+ii)
+
+if the authorization is an HMAC session or a password;
+(a) the TPMA_NV_AUTHWRITE attribute of the NV Index is SET if the command modifies
+the NV Index data (TPM_RC_AUTH_UNAVAILABLE);
+(b) the TPMA_NV_AUTHREAD attribute of the NV Index is SET if the command reads the
+NV Index data (TPM_RC_AUTH_UNAVAILABLE).
+
+g) If the authorization is provided by a policy session, then:
+1) if policySession→timeOut
+(TPM_RC_EXPIRED);
+
+has
+
+been
+
+set,
+
+the
+
+session
+
+shall
+
+not
+
+have
+
+expired
+
+2) if policySession→cpHash has been set, it shall match the cpHash of the command
+(TPM_RC_POLICY_FAIL);
+3) if policySession→commandCode has been set, then commandCode of the command shall match
+(TPM_RC_POLICY_CC);
+4) policySession→policyDigest
+(TPM_RC_POLICY_FAIL);
+
+shall
+
+match
+
+the
+
+authPolicy
+
+associated
+
+with
+
+the
+
+handle
+
+5) if policySession→pcrUpdateCounter has been set, then it shall match the value of
+pcrUpdateCounter (TPM_RC_PCR_CHANGED);
+6) if policySession->commandLocality has been set, it shall match the locality of the command
+(TPM_RC_LOCALITY), and
+7) if the authorization uses an HMAC, then the HMAC is properly constructed using the authValue
+associated with the handle and/or the session secret (TPM_RC_AUTH_FAIL or
+TPM_RC_BAD_AUTH).
+NOTE 5
+
+For a bound session, if the handle references the object us ed to initiate the session, then the
+authValue will not be required but proof of knowledge of the session secret is necessary.
+
+NOTE 6
+
+A policy session may require proof of knowledge of the authValue of the object being authorized.
+
+If the TPM returns an error other than TPM_RC_AUTH_FAIL then the TPM shall not alter any TPM state.
+If the TPM return TPM_RC_AUTH_FAIL, then the TPM shall not alter any TPM state other than
+lockoutCount.
+NOTE 7
+
+7.7
+
+The TPM may decrease failedTries regardless of any other processing performed by the TPM. That
+is, the TPM may exit Lockout mode, regardless of the return code.
+
+Parameter Decryption
+
+If an authorization session has the TPMA_SESSION.decrypt attribute SET, and the command does not
+allow a command parameter to be encrypted, then the TPM will return TPM_RC_ATTRIBUTES.
+
+Page 8
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Otherwise, the TPM will decrypt the parameter using the values associated with the session before
+parsing parameters.
+7.8
+7.8.1
+
+Parameter Unmarshaling
+Introduction
+
+The detailed actions for each command assume that the input parameters of the command have been
+unmarshaled into a command-specific structure with the structure defined by the command schematic.
+Additionally, a response-specific output structure is assumed which will receive the values produced by
+the detailed actions.
+NOTE
+
+An implementation is not required to process parameters in this manner or to separate the
+parameter parsing from the command actions. This method was chosen for the specification so that
+the normative behavior described by the detailed actions would be clear and unencumbered.
+
+Unmarshaling is the process of processing the parameters in the input buffer and preparing the
+parameters for use by the command-specific action code. No data movement need take place but it is
+required that the TPM validate that the parameters meet the requirements of the expected data type as
+defined in Part 2 of this specification.
+7.8.2
+
+Unmarshaling Errors
+
+When an error is encountered while unmarshaling a command parameter, an error response code is
+returned and no command processing occurs. A table defining a data type may have response codes
+embedded in the table to indicate the error returned when the input value does not match the parameters
+of the table.
+NOTE
+
+In the reference implementation, a parameter number is added to the response code so that the
+offending parameter can be isolated. This is optional.
+
+In many cases, the table contains no specific response code value and the return code will be determined
+as defined in Table 3.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 9
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+Table 3 — Unmarshaling Errors
+
+Response Code
+
+Meaning
+
+TPM_RC_ASYMMETRIC
+
+a parameter that should be an asymmetric algorithm selection does not have a
+value that is supported by the TPM
+
+TPM_RC_BAD_TAG
+
+a parameter that should be a command tag selection has a value that is not
+supported by the TPM
+
+TPM_RC_COMMAND_CODE
+
+a parameter that should be a command code does not have a value that is
+supported by the TPM
+
+TPM_RC_HASH
+
+a parameter that should be a hash algorithm selection does not have a value that
+is supported by the TPM
+
+TPM_RC_INSUFFICIENT
+
+the input buffer did not contain enough octets to allow unmarshaling of the
+expected data type;
+
+TPM_RC_KDF
+
+a parameter that should be a key derivation scheme (KDF) selection does not
+have a value that is supported by the TPM
+
+TPM_RC_KEY_SIZE
+
+a parameter that is a key size has a value that is not supported by the TPM
+
+TPM_RC_MODE
+
+a parameter that should be a symmetric encryption mode selection does not have
+a value that is supported by the TPM
+
+TPM_RC_RESERVED
+
+a non-zero value was found in a reserved field of an attribute structure (TPMA_)
+
+TPM_RC_SCHEME
+
+a parameter that should be signing or encryption scheme selection does not have
+a value that is supported by the TPM
+
+TPM_RC_SIZE
+
+the value of a size parameter is larger or smaller than allowed
+
+TPM_RC_SYMMETRIC
+
+a parameter that should be a symmetric algorithm selection does not have a
+value that is supported by the TPM
+
+TPM_RC_TAG
+
+a parameter that should be a structure tag has a value that is not supported by
+the TPM
+
+TPM_RC_TYPE
+
+The type parameter of a TPMT_PUBLIC or TPMT_SENSITIVE has a value that is
+not supported by the TPM
+
+TPM_RC_VALUE
+
+a parameter does not have one of its allowed values
+
+In some commands, a parameter may not be used because of various options of that command.
+However, the unmarshaling code is required to validate that all parameters have values that are allowed
+by the Part 2 definition of the parameter type even if that parameter is not used in the command actions.
+7.9
+
+Command Post Processing
+
+When the code that implements the detailed actions of the command completes, it returns a response
+code. If that code is not TPM_RC_SUCCESS, the post processing code will not update any session or
+audit data and will return a 10-octet response packet.
+If the command completes successfully, the tag of the command determines if any authorization sessions
+will be in the response. If so, the TPM will encrypt the first parameter of the response if indicated by the
+authorization attributes. The TPM will then generate a new nonce value for each session and, if
+appropriate, generate an HMAC.
+
+Page 10
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+NOTE 1
+
+The authorization attributes were validated during the session area validation to ensure that only
+one session was used for parameter encryption of the response and that the command allowed
+encryption in the response.
+
+NOTE 2
+
+No session nonce value is used for a password authorization but the session data is present.
+
+Additionally, if the command is being audited by Command Audit, the audit digest is updated with the
+cpHash of the command and rpHash of the response.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 11
+October 31, 2013
+
+ Part 3: Commands
+
+8
+8.1
+
+Trusted Platform Module Library
+
+Response Values
+Tag
+
+When a command completes successfully, the tag parameter in the response shall have the same value
+as the tag parameter in the command (TPM_ST_SESSIONS or TPM_RC_NO_SESSIONS). When a
+command fails (the responseCode is not TPM_RC_SUCCESS), then the tag parameter in the response
+shall be TPM_ST_NO_SESSIONS.
+A special case exists when the command tag parameter is not an allowed value (TPM_ST_SESSIONS or
+TPM_ST_NO_SESSIONS). For this case, it is assumed that the system software is attempting to send a
+command formatted for a TPM 1.2 but the TPM is not capable of executing TPM 1.2 commands. So that
+the TPM 1.2 compatible software will have a recognizable response, the TPM sets tag to
+TPM_ST_RSP_COMMAND, responseSize to 00 00 00 0A16 and responseCode to TPM_RC_BAD_TAG.
+This is the same response as the TPM 1.2 fatal error for TPM_BADTAG.
+8.2
+
+Response Codes
+
+The normal response for any command is TPM_RC_SUCCESS. Any other value indicates that the
+command did not complete and the state of the TPM is unchanged. An exception to this general rule is
+that the logic associated with dictionary attack protection is allowed to be modified when an authorization
+failure occurs.
+Commands have response codes that are specific to that command, and those response codes are
+enumerated in the detailed actions of each command. The codes associated with the unmarshaling of
+parameters are documented Table 3. Another set of response code value are not command specific and
+indicate a problem that is not specific to the command. That is, if the indicated problem is remedied, the
+same command could be resubmitted and may complete normally.
+The response codes that are not command specific are listed and described in Table 4.
+The reference code for the command actions may have code that generates specific response codes
+associated with a specific check but the listing of responses may not have that response code listed.
+
+Page 12
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 4 — Command-Independent Response Codes
+Response Code
+
+Meaning
+
+TPM_RC_CANCELLED
+
+This response code may be returned by a TPM that supports command cancel.
+When the TPM receives an indication that the current command should be
+cancelled, the TPM may complete the command or return this code. If this code
+is returned, then the TPM state is not changed and the same command may be
+retried.
+
+TPM_RC_CONTEXT_GAP
+
+This response code can be returned for commands that manage session
+contexts. It indicates that the gap between the lowest numbered active session
+and the highest numbered session is at the limits of the session tracking logic.
+The remedy is to load the session context with the lowest number so that its
+tracking number can be updated.
+
+TPM_RC_LOCKOUT
+
+This response indicates that authorizations for objects subject to DA protection
+are not allowed at this time because the TPM is in DA lockout mode. The remedy
+is to wait or to exeucte TPM2_DictionaryAttackLockoutReset().
+
+TPM_RC_MEMORY
+
+A TPM may use a common pool of memory for objects, sessions, and other
+purposes. When the TPM does not have enough memory available to perform
+the actions of the command, it may return TPM_RC_MEMORY. This indicates
+that the TPM resource manager may flush either sessions or objects in order to
+make memory available for the command execution. A TPM may choose to
+return TPM_RC_OBJECT_MEMORY or TPM_RC_SESSION_MEMORY if it
+needs contexts of a particular type to be flushed.
+
+TPM_RC_NV_RATE
+
+This response code indicates that the TPM is rate-limiting writes to the NV
+memory in order to prevent wearout. This response is possible for any command
+that explicity writes to NV or commands that incidentally use NV such as a
+command that uses authorization session that may need to update the dictionary
+attack logic.
+
+TPM_RC_NV_UNAVAILABLE
+
+This response code is similar to TPM_RC_NV_RATE but indicates that access to
+NV memory is currently not available and the command is not allowed to proceed
+until it is. This would occur in a system where the NV memory used by the TPM
+is not exclusive to the TPM and is a shared system resource.
+
+TPM_RC_OBJECT_HANDLES
+
+This response code indicates that the TPM has exhausted its handle space and
+no new objects can be loaded unless the TPM is rebooted. This does not occur in
+the reference implementation because of the way that object handles are
+allocated. However, other implementations are allowed to assign each object a
+unique handle each time the object is loaded. A TPM using this implementation
+24
+would be able to load 2 objects before the object space is exhausted.
+
+TPM_RC_OBJECT_MEMORY
+
+This response code can be returned by any command that causes the TPM to
+need an object 'slot'. The most common case where this might be returned is
+when an object is loaded (TPM2_Load, TPM2_CreatePrimary(), or
+TPM2_ContextLoad()). However, the TPM implementation is allowed to use
+object slots for other reasons. In the reference implementation, the TPM copies a
+referenced persistent object into RAM for the duration of the commannd. If all the
+slots are previously occupied, the TPM may return this value. A TPM is allowed
+to use object slots for other purposes and return this value. The remedy when
+this response is returned is for the TPM resource manager to flush a transient
+object.
+
+TPM_RC_REFERENCE_Hx
+
+This response code indicates that a handle in the handle area of the command is
+not associated with a loaded object. The value of 'x' is in the range 0 to 6 with a
+st
+th
+value of 0 indicating the 1 handle and 6 representing the 7 . The TPM resource
+manager needs to find the correct object and load it. It may then adjust the
+handle and retry the command.
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Usually, this error indicates that the TPM resource manager has a corrupted
+database.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 13
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Response Code
+
+Meaning
+
+TPM_RC_REFERENCE_Sx
+
+This response code indicates that a handle in the session area of the command
+is not associated with a loaded session. The value of 'x' is in the range 0 to 6 with
+st
+th
+a value of 0 indicating the 1 session handle and 6 representing the 7 . The
+TPM resource manager needs to find the correct session and load it. It may then
+retry the command.
+NOTE Usually, this error indicates that the TPM resource manager has a
+corrupted database.
+
+TPM_RC_RETRY
+
+the TPM was not able to start the command
+
+This response code indicates that the TPM does not have a handle to assign to a
+new session. This respose is only returned by TPM2_StartAuthSession(). It is
+TPM_RC_SESSION_HANDLES
+listed here because the command is not in error and the TPM resource manager
+can remedy the situation by flushing a session (TPM2_FlushContext().
+
+TPM_RC_SESSION_MEMORY
+
+This response code can be returned by any command that causes the TPM to
+need a session 'slot'. The most common case where this might be returned is
+when a session is loaded (TPM2_StartAuthSession() or TPM2_ContextLoad()).
+However, the TPM implementation is allowed to use object slots for other
+purposes. The remedy when this response is returned is for the TPM resource
+manager to flush a transient object.
+
+TPM_RC_SUCCESS
+
+Normal completion for any command. If the responseCode is
+TPM_RC_SESSIONS, then the rest of the response has the format indicated in
+the response schematic. Otherwise, the response is a 10 octet value indicating
+an error.
+
+TPM_RC_TESTING
+
+This response code indicates that the TPM is performing tests and cannot
+respond to the request at this time. The command may be retried.
+
+TPM_RC_YIELDED
+
+the TPM has suspended operation on the command; forward progress was made
+and the command may be retried.
+See Part 1, “Multi-tasking.”
+NOTE
+
+Page 14
+October 31, 2013
+
+This cannot occur on the reference implementation.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+9
+
+Part 3: Commands
+
+Implementation Dependent
+
+The actions code for each command makes assumptions about the behavior of various sub-systems.
+There are many possible implementations of the subsystems that would achieve equivalent results. The
+actions code is not written to anticipate all possible implementations of the sub-systems. Therefore, it is
+the responsibility of the implementer to ensure that the necessary changes are made to the actions code
+when the sub-system behavior changes.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 15
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Detailed Actions Assumptions
+
+10
+10.1
+
+Introduction
+
+The C code in the Detailed Actions for each command is written with a set of assumptions about the
+processing performed before the action code is called and the processing that will be done after the
+action code completes.
+10.2
+
+Pre-processing
+
+Before calling the command actions code, the following actions have occurred.
+
+
+Verification that the handles in the handle area reference entities that are resident on the TPM.
+NOTE
+
+If a handle is in the parameter portion of the command, the associated entity does not have to
+be loaded, but the handle is required to be the correct type.
+
+
+
+If use of a handle requires authorization, the Password, HMAC, or Policy session associated with the
+handle has been verified.
+
+
+
+If a command parameter was encrypted using parameter encryption, it was decrypted before being
+unmarshaled.
+
+
+
+If the command uses handles or parameters, the calling stack contains a pointer to a data structure
+(in) that holds the unmarshaled values for the handles and commands. If the response has handles
+or parameters, the calling stack contains a pointer to a data structure ( out) to hold the handles and
+parameters generated by the command.
+
+
+
+All parameters of the in structure have been validated and meet the requirements of the parameter
+type as defined in Part 2.
+
+
+
+Space set aside for the out structure is sufficient to hold the largest out structure that could be
+produced by the command
+
+10.3
+
+Post Processing
+
+When the function implementing the command actions completes,
+
+
+response parameters that require parameter encryption will be encrypted after the command actions
+complete;
+
+
+
+audit and session contexts will be updated if the command response is TPM_RC_SUCCESS; and
+
+
+
+the command header and command response parameters will be marshaled to the response buffer.
+
+Page 16
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+11
+
+Part 3: Commands
+
+Start-up
+
+11.1
+
+Introduction
+
+This clause contains the commands used to manage the startup and restart state of a TPM.
+11.2
+
+_TPM_Init
+
+11.2.1 General Description
+_TPM_Init initializes a TPM.
+Initialization actions include testing code required to execute the next expected command. If the TPM is in
+FUM, the next expected command is TPM2_FieldUpgradeData(); otherwise, the next expected command
+is TPM2_Startup().
+NOTE 1
+
+If the TPM performs self-tests after receiving _TPM_Init() and the TPM enters Failure mode before
+receiving TPM2_Startup() or TPM2_FieldUpgradeData(), then the TPM may be able to accept
+TPM2_GetTestResult() or TPM2_GetCapability().
+
+The means of signaling _TPM_Init shall be defined in the platform-specific specifications that define the
+physical interface to the TPM. The platform shall send this indication whenever the platform starts its boot
+process and only when the platform starts its boot process.
+There shall be no software method of generating this indication that does not also reset the platform and
+begin execution of the CRTM.
+NOTE 2
+
+In the reference implementation, this signal causes an internal flag ( s_initialized) to be CLEAR.
+While this flag is CLEAR, the TPM will only accept the next expected command described above.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 17
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+11.2.2 Detailed Actions
+1
+
+#include "InternalRoutines.h"
+
+This function is used to process a _TPM_Init() indication.
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
+void _TPM_Init(void)
+{
+// Initialize crypto engine
+CryptInitUnits();
+// Initialize NV environment
+NvPowerOn();
+// Start clock
+TimePowerOn();
+// Set initialization state
+TPMInit();
+// Set g_DRTMHandle as unassigned
+g_DRTMHandle = TPM_RH_UNASSIGNED;
+// No H-CRTM, yet.
+g_DrtmPreStartup = FALSE;
+return;
+}
+
+Page 18
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+11.3
+
+Part 3: Commands
+
+TPM2_Startup
+
+11.3.1 General Description
+TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that TPM initialization
+is necessary because of a system-wide reset. TPM2_Startup() is only valid after _TPM_Init Additional
+TPM2_Startup() commands are not allowed after it has completed successfully. If a TPM requires
+TPM2_Startup() and another command is received, or if the TPM receives TPM2_Startup() when it is not
+required, the TPM shall return TPM_RC_INITIALIZE.
+NOTE 1
+
+See 11.2.1 for other command options for a TPM supporting field upgrade mode.
+
+NOTE 2
+
+_TPM_Hash_Start, _TPM_Hash_Data, and _TPM_Hash_End are not commands and a platform specific specification may allow these indications between _TPM_Init and TPM2_Startup().
+
+If in Failure mode the TPM shall accept TPM2_GetTestResult() and TPM2_GetCapability() even if
+TPM2_Startup() is not completed successfully or processed at all.
+A Shutdown/Startup sequence determines the way in which the TPM will operate in response to
+TPM2_Startup(). The three sequences are:
+1) TPM Reset – This is a Startup(CLEAR) preceded by either Shutdown(CLEAR) or no
+TPM2_Shutdown(). On TPM Reset, all variables go back to their default initialization state.
+NOTE 3
+
+Only those values that are specified as having a default initialization state are changed by TPM
+Reset. Persistent values that have no default initialization state are not changed by this
+command. Values such as seeds have no default initialization state and only change due to
+specific commands.
+
+2) TPM Restart – This is a Startup(CLEAR) preceded by Shutdown(STATE). This preserves much of the
+previous state of the TPM except that PCR and the controls associated with the Platform hierarchy
+are all returned to their default initialization state;
+3) TPM Resume – This is a Startup(STATE) preceded by Shutdown(STATE). This preserves the
+previous state of the TPM including the static Root of Trust for Measurement (S-RTM) PCR and the
+platform controls other than the phEnable and phEnableNV.
+If a TPM receives Startup(STATE) and that was not preceded by Shutdown(STATE), the TPM shall return
+TPM_RC_VALUE.
+If, during TPM Restart or TPM Resume, the TPM fails to restore the state saved at the last
+Shutdown(STATE), the TPM shall enter Failure Mode and return TPM_RC_FAILURE.
+On any TPM2_Startup(),
+
+
+phEnable and phEnableNV shall be SET;
+
+
+
+all transient contexts (objects, sessions, and sequences) shall be flushed from TPM memory;
+
+
+
+TPMS_TIME_INFO.time shall be reset to zero; and
+
+
+
+use of lockoutAuth shall be enabled if lockoutRecovery is zero.
+
+Additional actions are performed based on the Shutdown/Startup sequence.
+On TPM Reset
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 19
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+
+
+platformAuth and platformPolicy shall be set to the Empty Buffer,
+
+
+
+tracking data for saved session contexts shall be set to its initial value,
+
+
+
+the object context sequence number is reset to zero,
+
+
+
+a new context encryption key shall be generated,
+
+
+
+TPMS_CLOCK_INFO.restartCount shall be reset to zero,
+
+
+
+TPMS_CLOCK_INFO.resetCount shall be incremented,
+
+
+
+the PCR Update Counter shall be clear to zero,
+
+
+
+shEnable and ehEnable shall be SET, and
+
+
+
+PCR in all banks are reset to their default initial conditions as determined by the relevant platformspecific specification.
+NOTE 4
+
+PCR may be initialized any time between _TPM_Init and the end of TPM2_Startup(). PCR that
+are preserved by TPM Resume will need to be restored during TPM2_Startup().
+
+NOTE 5
+
+See "Initializing PCR" in Part 1 of this specification for a description of the default initial
+conditions for a PCR.
+
+On TPM Restart
+
+
+TPMS_CLOCK_INFO.restartCount shall be incremented,
+
+
+
+shEnable and ehEnable shall be SET,
+
+
+
+platformAuth and platformPolicy shall be set to the Empty Buffer, and
+
+
+
+PCR in all banks are reset to their default initial conditions.
+
+
+
+If a CRTM Event sequence is active, extend the PCR designated by the platform-specific
+specification.
+
+On TPM Resume
+
+
+the H-CRTM startup method is the same for this TPM2_Startup() as for the previous TPM2_Startup();
+(TPM_RC_LOCALITY)
+
+
+
+TPMS_CLOCK_INFO.restartCount shall be incremented; and
+
+
+
+PCR that are specified in a platform-specific specification to be preserved on TPM Resume are
+restored to their saved state and other PCR are set to their initial value as determined by a platformspecific specification.
+
+Other TPM state may change as required to meet the needs of the implementation.
+If the startupType is TPM_SU_STATE and the TPM requires TPM_SU_CLEAR, then the TPM shall return
+TPM_RC_VALUE.
+NOTE 6
+
+The TPM will require
+Shutdown(CLEAR).
+
+NOTE 7
+
+If startupType is neither TPM_SU_STATE nor TPM_SU_CLEAR, then the unmarshaling code returns
+TPM_RC_VALUE.
+
+Page 20
+October 31, 2013
+
+TPM_SU_CLEAR
+
+when
+
+no
+
+Published
+Copyright © TCG 2006-2013
+
+shutdown
+
+was
+
+performed
+
+or
+
+after
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+11.3.2 Command and Response
+Table 5 — TPM2_Startup Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Startup {NV}
+
+TPM_SU
+
+startupType
+
+TPM_SU_CLEAR or TPM_SU_STATE
+
+Table 6 — TPM2_Startup Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 21
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+11.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Startup_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+start up type is not compatible with previous shutdown sequence
+
+TPM_RC
+TPM2_Startup(
+Startup_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+STARTUP_TYPE
+TPM_RC
+BOOL
+
+startup;
+result;
+prevDrtmPreStartup;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation
+// Read orderly shutdown states from previous power cycle
+NvReadReserved(NV_ORDERLY, &g_prevOrderlyState);
+// HACK to extract the DRTM startup type associated with the previous shutdown
+prevDrtmPreStartup = (g_prevOrderlyState == (TPM_SU_STATE + 0x8000));
+if(prevDrtmPreStartup)
+g_prevOrderlyState = TPM_SU_STATE;
+// if the previous power cycle was shut down with no StateSave command, or
+// with StateSave command for CLEAR, this cycle can not startup up with
+// STATE
+if(
+(
+g_prevOrderlyState == SHUTDOWN_NONE
+|| g_prevOrderlyState == TPM_SU_CLEAR
+)
+&& in->startupType == TPM_SU_STATE
+)
+return TPM_RC_VALUE + RC_Startup_startupType;
+// Internal Date Update
+// Translate the TPM2_ShutDown and TPM2_Startup sequence into the startup
+// types.
+if(in->startupType == TPM_SU_CLEAR && g_prevOrderlyState == TPM_SU_STATE)
+{
+startup = SU_RESTART;
+// Read state reset data
+NvReadReserved(NV_STATE_RESET, &gr);
+}
+else if(in->startupType == TPM_SU_STATE && g_prevOrderlyState == TPM_SU_STATE)
+{
+// For a resume, the H-CRTM startup method must be the same
+if(g_DrtmPreStartup != prevDrtmPreStartup)
+return TPM_RC_LOCALITY;
+
+Page 22
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+
+Part 3: Commands
+
+// Read state clear and state reset data
+NvReadReserved(NV_STATE_CLEAR, &gc);
+NvReadReserved(NV_STATE_RESET, &gr);
+startup = SU_RESUME;
+}
+else
+{
+startup = SU_RESET;
+}
+// Read persistent data from NV
+NvReadPersistent();
+// Crypto Startup
+CryptUtilStartup(startup);
+// Start up subsystems
+// Start counters and timers
+TimeStartup(startup);
+// Start dictionary attack subsystem
+DAStartup(startup);
+// Enable hierarchies
+HierarchyStartup(startup);
+// Restore/Initialize PCR
+PCRStartup(startup);
+// Restore/Initialize command audit information
+CommandAuditStartup(startup);
+// Object context variables
+if(startup == SU_RESET)
+{
+// Reset object context ID to 0
+gr.objectContextID = 0;
+// Reset clearCount to 0
+gr.clearCount= 0;
+}
+// Initialize object table
+ObjectStartup();
+// Initialize session table
+SessionStartup(startup);
+// Initialize index/evict data.
+// in NV index
+NvEntityStartup(startup);
+
+This function clear read/write locks
+
+// Initialize the orderly shut down flag for this cycle to SHUTDOWN_NONE.
+gp.orderlyState = SHUTDOWN_NONE;
+NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
+// Update TPM internal states if command succeeded.
+// Record a TPM2_Startup command has been received.
+TPMRegisterStartup();
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 23
+October 31, 2013
+
+ Part 3: Commands
+
+11.4
+
+Trusted Platform Module Library
+
+TPM2_Shutdown
+
+11.4.1 General Description
+This command is used to prepare the TPM for a power cycle. The shutdownType parameter indicates
+how the subsequent TPM2_Startup() will be processed.
+For a shutdownType of any type, the volatile portion of Clock is saved to NV memory and the orderly
+shutdown indication is SET. NV with the TPMA_NV_ORDERY attribute will be updated.
+For a shutdownType of TPM_SU_STATE, the following additional items are saved:
+
+
+tracking information for saved session contexts;
+
+
+
+the session context counter;
+
+
+
+PCR that are designated as being preserved by TPM2_Shutdown(TPM_SU_STATE);
+
+
+
+the PCR Update Counter;
+
+
+
+flags associated with supporting the TPMA_NV_WRITESTCLEAR and TPMA_NV_READSTCLEAR
+attributes; and
+
+
+
+the command audit digest and count.
+
+The following items shall not be saved and will not be in TPM memory after the next TPM2_Startup:
+
+
+TPM-memory-resident session contexts;
+
+
+
+TPM-memory-resident transient objects; or
+
+
+
+TPM-memory-resident hash contexts created by TPM2_HashSequenceStart().
+
+Some values may be either derived from other values or saved to NV memory.
+This command saves TPM state but does not change the state other than the internal indication that the
+context has been saved. The TPM shall continue to accept commands. If a subsequent command
+changes TPM state saved by this command, then the effect of this command is nullified. The TPM MAY
+nullify this command for any subsequent command rather than check whether the command changed
+state saved by this command. If this command is nullified. and if no TPM2_Shutdown() occurs before the
+next TPM2_Startup(), then the next TPM2_Startup() shall be TPM2_Startup(CLEAR).
+
+Page 24
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+11.4.2 Command and Response
+Table 7 — TPM2_Shutdown Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Shutdown {NV}
+
+TPM_SU
+
+shutdownType
+
+TPM_SU_CLEAR or TPM_SU_STATE
+
+Table 8 — TPM2_Shutdown Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 25
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+11.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Shutdown_fp.h"
+Error Returns
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+if PCR bank has been re-configured, a CLEAR StateSave() is
+required
+
+TPM_RC
+TPM2_Shutdown(
+Shutdown_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// If PCR bank has been reconfigured, a CLEAR state save is required
+if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE)
+return TPM_RC_TYPE + RC_Shutdown_shutdownType;
+// Internal Data Update
+// PCR private date state save
+PCRStateSave(in->shutdownType);
+// Get DRBG state
+CryptDrbgGetPutState(GET_STATE);
+// Save all orderly data
+NvWriteReserved(NV_ORDERLY_DATA, &go);
+// Save RAM backed NV index data
+NvStateSave();
+if(in->shutdownType == TPM_SU_STATE)
+{
+// Save STATE_RESET and STATE_CLEAR data
+NvWriteReserved(NV_STATE_CLEAR, &gc);
+NvWriteReserved(NV_STATE_RESET, &gr);
+}
+else if(in->shutdownType == TPM_SU_CLEAR)
+{
+// Save STATE_RESET data
+NvWriteReserved(NV_STATE_RESET, &gr);
+}
+// Write orderly shut down state
+if(in->shutdownType == TPM_SU_CLEAR)
+gp.orderlyState = TPM_SU_CLEAR;
+else if(in->shutdownType == TPM_SU_STATE)
+gp.orderlyState = TPM_SU_STATE;
+else
+
+Page 26
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+55
+56
+57
+58
+59
+
+Part 3: Commands
+
+pAssert(FALSE);
+NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 27
+October 31, 2013
+
+ Part 3: Commands
+
+12
+12.1
+
+Trusted Platform Module Library
+
+Testing
+Introduction
+
+Compliance to standards for hardware security modules may require that the TPM test its functions
+before the results that depend on those functions may be returned. The TPM may perform operations
+using testable functions before those functions have been tested as long as the TPM returns no value
+that depends on the correctness of the testable function.
+EXAMPLE
+
+TPM2_PCR_Event() may be executed before the hash algorithms have been tested. However, until
+the hash algorithms have been tested, the contents of a PCR may not be used in any command if
+that command may result in a value being returned to the TPM user. This means tha t
+TPM2_PCR_Read() or TPM2_PolicyPCR() could not complete until the hashes have been checked
+but other TPM2_PCR_Event() commands may be executed even though the operation uses previous
+PCR values.
+
+If a command is received that requires return of a value that depends on untested functions, the TPM
+shall test the required functions before completing the command.
+Once the TPM has received TPM2_SelfTest() and before completion of all tests, the TPM is required to
+return TPM_RC_TESTING for any command that uses a function that requires a test.
+If a self-test fails at any time, the TPM will enter Failure mode. While in Failure mode, the TPM will return
+TPM_RC_FAILURE for any command other than TPM2_GetTestResult() and TPM2_GetCapability(). The
+TPM will remain in Failure mode until the next _TPM_Init.
+
+Page 28
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+12.2
+
+Part 3: Commands
+
+TPM2_SelfTest
+
+12.2.1 General Description
+This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, the TPM will test
+all functions. If fullTest = NO, the TPM will only test those functions that have not previously been tested.
+If any tests are required, the TPM shall either
+a) return TPM_RC_TESTING and begin self-test of the required functions, or
+NOTE 1
+
+If fullTest is NO, and all functions have been tested, the TPM shall return TPM_RC_SUCCESS.
+
+b) perform the tests and return the test result when complete.
+If the TPM uses option a), the TPM shall return TPM_RC_TESTING for any command that requires use
+of a testable function, even if the functions required for completion of the command have already been
+tested.
+NOTE 2
+
+This command may cause the TPM to continue processing after it has returned the response. So
+that software can be notified of the completion of the testing, the interface may include controls that
+would allow the TPM to generate an interrupt when the “background” processing is complete. This
+would be in addition to the interrupt may be available for signaling normal command completion. It is
+not necessary that there be two interrupts, but the interface should provide a way to indicate the
+nature of the interrupt (normal command or deferred command).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 29
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+12.2.2 Command and Response
+Table 9 — TPM2_SelfTest Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SelfTest {NV}
+
+TPMI_YES_NO
+
+fullTest
+
+YES if full test to be performed
+NO if only test of untested functions required
+
+Table 10 — TPM2_SelfTest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 30
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+12.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "SelfTest_fp.h"
+Error Returns
+TPM_RC_TESTING
+
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+Meaning
+self test in process
+
+TPM_RC
+TPM2_SelfTest(
+SelfTest_In
+)
+{
+// Command Output
+
+*in
+
+// IN: input parameter list
+
+// Call self test function in crypt module
+return CryptSelfTest(in->fullTest);
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 31
+October 31, 2013
+
+ Part 3: Commands
+
+12.3
+
+Trusted Platform Module Library
+
+TPM2_IncrementalSelfTest
+
+12.3.1 General Description
+This command causes the TPM to perform a test of the selected algorithms.
+NOTE 1
+
+The toTest list indicates the algorithms that software would like the TPM to test in anticipation of
+future use. This allows tests to be done so that a future commands will not be delayed due to
+testing.
+
+If toTest contains an algorithm that has already been tested, it will not be tested again.
+NOTE 2
+
+The only way to force retesting of an algorithm is with TPM2_SelfTest( fullTest = YES).
+
+The TPM will return in toDoList a list of algorithms that are yet to be tested. This list is not the list of
+algorithms that are scheduled to be tested but the algorithms/functions that have not been tested. Only
+the algorithms on the toTest list are scheduled to be tested by this command.
+Making toTest an empty list allows the determination of the algorithms that remain untested without
+triggering any testing.
+If toTest is not an empty list, the TPM shall return TPM_RC_SUCCESS for this command and then return
+TPM_RC_TESTING for any subsequent command (including TPM2_IncrementalSelfTest()) until the
+requested testing is complete.
+NOTE 3
+
+If toDoList is empty, then no additional tests are required and TPM_RC_TESTING will not be
+returned in subsequent commands and no additional delay will occur in a command due to testing.
+
+NOTE 4
+
+If none of the algorithms listed in toTest is in the toDoList, then no tests will be performed.
+
+If all the parameters in this command are valid, the TPM returns TPM_RC_SUCCESS and the toDoList
+(which may be empty).
+NOTE 5
+
+An implementation may perform all requested tests before returning TPM_RC_SUCCESS, or it may
+return TPM_RC_SUCCESS for this command and then return TPM_RC_TESTING for all
+subsequence commands (including TPM2_IncrementatSelfTest()) until the requested tests are
+complete.
+
+Page 32
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+12.3.2 Command and Response
+Table 11 — TPM2_IncrementalSelfTest Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_IncrementalSelfTest {NV}
+
+TPML_ALG
+
+toTest
+
+list of algorithms that should be tested
+
+Table 12 — TPM2_IncrementalSelfTest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPML_ALG
+
+toDoList
+
+Family “2.0”
+Level 00 Revision 00.99
+
+list of algorithms that need testing
+
+Published
+Copyright © TCG 2006-2013
+
+Page 33
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+12.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+#include "InternalRoutines.h"
+#include "IncrementalSelfTest_fp.h"
+
+TPM_RC
+TPM2_IncrementalSelfTest(
+IncrementalSelfTest_In
+IncrementalSelfTest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Call incremental self test function in crypt module
+return CryptIncrementalSelfTest(&in->toTest, &out->toDoList);
+}
+
+Page 34
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+12.4
+
+Part 3: Commands
+
+TPM2_GetTestResult
+
+12.4.1 General Description
+This command returns manufacturer-specific information regarding the results of a self-test and an
+indication of the test status.
+If TPM2_SelfTest() has not been executed and a testable function has not been tested, testResult will be
+TPM_RC_NEEDS_TEST. If TPM2_SelfTest() has been received and the tests are not complete,
+testResult will be TPM_RC_TESTING. If testing of all functions is complete without functional failures,
+testResult will be TPM_RC_SUCCESS. If any test failed, testResult will be TPM_RC_FAILURE. If the
+TPM is in Failure mode because of an invalid startupType in TPM2_Startup(), testResult will be
+TPM_RC_INITIALIZE.
+This command will operate when the TPM is in Failure mode so that software can determine the test
+status of the TPM and so that diagnostic information can be obtained for use in failure analysis. If the
+TPM is in Failure mode, then tag is required to be TPM_ST_NO_SESSIONS or the TPM shall return
+TPM_RC_FAILURE.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 35
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+12.4.2 Command and Response
+Table 13 — TPM2_GetTestResult Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetTestResult
+
+Table 14 — TPM2_GetTestResult Response
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_BUFFER
+
+outData
+
+TPM_RC
+
+testResult
+
+Page 36
+October 31, 2013
+
+test result data
+contains manufacturer-specific information
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+12.4.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+#include "InternalRoutines.h"
+#include "GetTestResult_fp.h"
+
+TPM_RC
+TPM2_GetTestResult(
+GetTestResult_Out
+)
+{
+// Command Output
+
+*out
+
+// OUT: output parameter list
+
+// Call incremental self test function in crypt module
+out->testResult = CryptGetTestResult(&out->outData);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 37
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Session Commands
+
+13
+13.1
+
+TPM2_StartAuthSession
+
+13.1.1 General Description
+This command is used to start an authorization session using alternative methods of establishing the
+session key (sessionKey). The session key is then used to derive values used for authorization and for
+encrypting parameters.
+This command allows injection of a secret into the TPM using either asymmetric or symmetric encryption.
+The type of tpmKey determines how the value in encryptedSalt is encrypted. The decrypted secret value
+is used to compute the sessionKey.
+NOTE 1
+
+If tpmKey Is TPM_RH_NULL, then encryptedSalt is required to be an Empty Buffer.
+
+The label value of “SECRET” (see “Terms and Definitions” in Part 1 of this specification) is used in the
+recovery of the secret value.
+The TPM generates the sessionKey from the recovered secret value.
+No authorization is required for tpmKey or bind.
+NOTE 2
+
+The justification for using tpmKey without providing authorization is that the result o f using the key is
+not available to the caller, except indirectly through the sessionKey. This does not represent a point
+of attack on the value of the key. If the caller attempts to use the session without knowing the
+sessionKey value, it is an authorization failure that will trigger the dictionary attack logic.
+
+The entity referenced with the bind parameter contributes an authorization value to the sessionKey
+generation process.
+If both tpmKey and bind are TPM_ALG_NULL, then sessionKey is set to the Empty Buffer. If tpmKey is
+not TPM_ALG_NULL, then encryptedSalt is used in the computation of sessionKey. If bind is not
+TPM_ALG_NULL, the authValue of bind is used in the sessionKey computation.
+If symmetric specifies a block cipher, then TPM_ALG_CFB is the only allowed value for the mode field in
+the symmetric parameter (TPM_RC_MODE).
+This command starts an authorization session and returns the session handle along with an initial
+nonceTPM in the response.
+If the TPM does not have
+TPM_RC_SESSION_HANDLES.
+
+a
+
+free
+
+slot
+
+for
+
+an
+
+authorization
+
+session,
+
+it
+
+shall
+
+return
+
+If the TPM implements a “gap” scheme for assigning contextID values, then the TPM shall return
+TPM_RC_CONTEXT_GAP if creating the session would prevent recycling of old saved contexts (See
+“Context Management” in Part 1).
+If tpmKey is not TPM_ALG_NULL then encryptedSalt shall be a TPM2B_ENCRYPTED_SECRET of the
+proper type for tpmKey. The TPM shall return TPM_RC_VALUE if:
+a) tpmKey references an RSA key and
+1) encryptedSalt does not contain a value that is the size of the public modulus of tpmKey,
+2) encryptedSalt has a value that is greater than the public modulus of tpmKey,
+3) encryptedSalt is not a properly encode OAEP value, or
+4) the decrypted salt value is larger than the size of the digest produced by the nameAlg of tpmKey;
+or
+
+Page 38
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+b) tpmKey references an ECC key and encryptedSalt
+1) does not contain a TPMS_ECC_POINT or
+2) is not a point on the curve of tpmKey;
+NOTE 3
+
+When ECC is used, the point multiply process produces a value (Z) that is used in a KDF to
+produce the final secret value. The size of the secret value is an input parameter to the KDF
+and the result will be set to be the size of the digest produced by the nameAlg of tpmKey.
+
+c) tpmKey references a symmetric block cipher or a keyedHash object and encryptedSalt contains a
+value that is larger than the size of the digest produced by the nameAlg of tpmKey.
+For all session types, this command will cause initialization of the sessionKey and may establish binding
+between the session and an object (the bind object). If sessionType is TPM_SE_POLICY or
+TPM_SE_TRIAL, the additional session initialization is:
+
+
+set policySession→policyDigest to a Zero Digest (the digest size for policySession→policyDigest is
+the size of the digest produced by authHash);
+
+
+
+authorization may be given at any locality;
+
+
+
+authorization may apply to any command code;
+
+
+
+authorization may apply to any command parameters or handles;
+
+
+
+the authorization has no time limit;
+
+
+
+an authValue is not needed when the authorization is used;
+
+
+
+the session is not bound;
+
+
+
+the session is not an audit session; and
+
+
+
+the time at which the policy session was created is recorded.
+
+Additionally, if sessionType is TPM_SE_TRIAL, the session will not be usable for authorization but can be
+used to compute the authPolicy for an object.
+NOTE 4
+
+Although this command changes the session allocation information in the TPM, it does not invalidate
+a saved context. That is, TPM2_Shutdown() is not required after this comm and in order to reestablish the orderly state of the TPM. This is because the created context will occupy an available
+slot in the TPM and sessions in the TPM do not survive any TPM2_Startup(). However, if a created
+session is context saved, the orderly state does change.
+
+The TPM shall return TPM_RC_SIZE if nonceCaller is less than 16 octets or is greater than the size of
+the digest produced by authHash.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 39
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+13.1.2 Command and Response
+Table 15 — TPM2_StartAuthSession Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_StartAuthSession
+
+tpmKey
+
+handle of a loaded decrypt key used to encrypt salt
+may be TPM_RH_NULL
+Auth Index: None
+
+TPMI_DH_ENTITY+
+
+bind
+
+entity providing the authValue
+may be TPM_RH_NULL
+Auth Index: None
+
+TPM2B_NONCE
+
+nonceCaller
+
+TPMI_DH_OBJECT+
+
+Description
+
+initial nonceCaller, sets nonce size for the session
+shall be at least 16 octets
+
+TPM2B_ENCRYPTED_SECRET encryptedSalt
+
+value encrypted according to the type of tpmKey
+If tpmKey is TPM_RH_NULL, this shall be the Empty
+Buffer.
+
+TPM_SE
+
+sessionType
+
+indicates the type of the session; simple HMAC or policy
+(including a trial policy)
+
+TPMT_SYM_DEF+
+
+symmetric
+
+the algorithm and key size for parameter encryption
+may select TPM_ALG_NULL
+
+TPMI_ALG_HASH
+
+authHash
+
+hash algorithm to use for the session
+Shall be a hash algorithm supported by the TPM and
+not TPM_ALG_NULL
+
+Table 16 — TPM2_StartAuthSession Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_SH_AUTH_SESSION
+
+sessionHandle
+
+handle for the newly created session
+
+TPM2B_NONCE
+
+nonceTPM
+
+the initial nonce from the TPM, used in the computation
+of the sessionKey
+
+Page 40
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+13.1.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "StartAuthSession_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+tpmKey does not reference a decrypt key
+
+TPM_RC_CONTEXT_GAP
+
+the difference between the most recently created active context and
+the oldest active context is at the limits of the TPM
+
+TPM_RC_HANDLE
+
+input decrypt key handle only has public portion loaded
+
+TPM_RC_MODE
+
+symmetric specifies a block cipher but the mode is not
+TPM_ALG_CFB.
+
+TPM_RC_SESSION_HANDLES
+
+no session handle is available
+
+TPM_RC_SESSION_MEMORY
+
+no more slots for loading a session
+
+TPM_RC_SIZE
+
+nonce less than 16 octets or greater than the size of the digest
+produced by authHash
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+
+Meaning
+
+secret size does not match decrypt key type; or the recovered secret
+is larget than the digest size of the nameAlg of tpmKey; or, for an
+RSA decrypt key, if encryptedSecret is greater than the public
+exponent of tpmKey.
+
+TPM_RC
+TPM2_StartAuthSession(
+StartAuthSession_In
+StartAuthSession_Out
+
+*in,
+*out
+
+// IN: input parameter buffer
+// OUT: output parameter buffer
+
+TPM_RC
+OBJECT
+SESSION
+TPM2B_DATA
+
+result = TPM_RC_SUCCESS;
+*tpmKey;
+// TPM key for decrypt salt
+*session;
+// session internal data
+salt;
+
+)
+{
+
+// Input Validation
+// Check input nonce size. IT should be at least 16 bytes but not larger
+// than the digest size of session hash.
+if(
+in->nonceCaller.t.size < 16
+|| in->nonceCaller.t.size > CryptGetHashDigestSize(in->authHash))
+return TPM_RC_SIZE + RC_StartAuthSession_nonceCaller;
+// If an decrypt key is passed in, check its validation
+if(in->tpmKey != TPM_RH_NULL)
+{
+// secret size cannot be 0
+if(in->encryptedSalt.t.size == 0)
+return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
+// Get pointer to loaded decrypt key
+tpmKey = ObjectGet(in->tpmKey);
+// Decrypting salt requires accessing the private portion of a key.
+// Therefore, tmpKey can not be a key with only public portion loaded
+if(tpmKey->attributes.publicOnly)
+return TPM_RC_HANDLE + RC_StartAuthSession_tpmKey;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 41
+October 31, 2013
+
+ Part 3: Commands
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+
+Trusted Platform Module Library
+
+// HMAC session input handle check.
+// tpmKey should be a decryption key
+if(tpmKey->publicArea.objectAttributes.decrypt != SET)
+return TPM_RC_ATTRIBUTES + RC_StartAuthSession_tpmKey;
+// Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors
+// may be returned at this point
+result = CryptSecretDecrypt(in->tpmKey, &in->nonceCaller, "SECRET",
+&in->encryptedSalt, &salt);
+if(result != TPM_RC_SUCCESS)
+return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
+}
+else
+{
+// secret size must be 0
+if(in->encryptedSalt.t.size != 0)
+return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
+salt.t.size = 0;
+}
+// If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR)
+// then the mode must be CFB.
+if(
+in->symmetric.algorithm != TPM_ALG_NULL
+&& in->symmetric.algorithm != TPM_ALG_XOR
+&& in->symmetric.mode.sym != TPM_ALG_CFB)
+return TPM_RC_MODE + RC_StartAuthSession_symmetric;
+// Internal Data Update
+// Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES
+// or TPM_RC_SESSION_MEMORY errors may be returned returned at this point.
+//
+// The detailed actions for creating the session context are not shown here
+// as the details are implementation dependent
+// SessionCreate sets the output handle
+result = SessionCreate(in->sessionType, in->authHash,
+&in->nonceCaller, &in->symmetric,
+in->bind, &salt, &out->sessionHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Command Output
+// Get session pointer
+session = SessionGet(out->sessionHandle);
+// Copy nonceTPM
+out->nonceTPM = session->nonceTPM;
+return TPM_RC_SUCCESS;
+}
+
+Page 42
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+13.2
+
+Part 3: Commands
+
+TPM2_PolicyRestart
+
+13.2.1 General Description
+This command allows a policy authorization session to be returned to its initial state. This command is
+used after the TPM returns TPM_RC_PCR_CHANGED. That response code indicates that a policy will
+fail because the PCR have changed after TPM2_PolicyPCR() was executed. Restarting the session
+allows the authorizations to be replayed because the session restarts with the same nonceTPM. If the
+PCR are valid for the policy, the policy may then succeed.
+This command does not reset the policy ID or the policy start time.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 43
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+13.2.2 Command and Response
+Table 17 — TPM2_PolicyRestart Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyRestart
+
+TPMI_SH_POLICY
+
+sessionHandle
+
+the handle for the policy session
+
+Table 18 — TPM2_PolicyRestart Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 44
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+13.2.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
+#include "InternalRoutines.h"
+#include "PolicyRestart_fp.h"
+
+TPM_RC
+TPM2_PolicyRestart(
+PolicyRestart_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+BOOL
+
+*session;
+wasTrialSession;
+
+)
+{
+
+// Internal Data Update
+session = SessionGet(in->sessionHandle);
+wasTrialSession = session->attributes.isTrialPolicy == SET;
+// Initialize policy session
+SessionResetPolicyData(session);
+session->attributes.isTrialPolicy = wasTrialSession;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 45
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Object Commands
+
+14
+14.1
+
+TPM2_Create
+
+14.1.1 General Description
+This command is used to create an object that can be loaded into a TPM using TPM2_Load(). If the
+command completes successfully, the TPM will create the new object and return the object’s creation
+data (creationData), its public area (outPublic), and its encrypted sensitive area (outPrivate). Preservation
+of the returned data is the responsibility of the caller. The object will need to be loaded (TPM2_Load())
+before it may be used.
+TPM2B_PUBLIC template (inPublic) contains all of the fields necessary to define the properties of the
+new object. The setting for these fields is defined in “Public Area Template” in Part 1 and
+“TPMA_OBJECT” in Part 2.
+The parentHandle parameter shall reference a loaded decryption key that has both the public and
+sensitive area loaded.
+When defining the object, the caller provides a template structure for the object in a TPM2B_PUBLIC
+structure (inPublic), an initial value for the object’s authValue (inSensitive.authValue), and, if the object is
+a symmetric object, an optional initial data value (inSensitive.data). The TPM shall validate the
+consistency of inPublic.attributes according to the Creation rules in “TPMA_OBJECT” in Part 2.
+The sensitive parameter may be encrypted using parameter encryption.
+The methods in this clause are used by both TPM2_Create() and TPM2_CreatePrimary(). When a value
+is indicated as being TPM-generated, the value is filled in by bits from the RNG if the command is
+TPM2_Create() and with values from KDFa() if the command is TPM2_CreatePrimary(). The parameters
+of each creation value are specified in Part 1.
+The sensitiveDataOrigin attribute of inPublic shall be SET if inSensitive.data is an Empty Buffer and
+CLEAR if inSensitive.data is not an Empty Buffer or the TPM shall return TPM_RC_ATTRIBUTES.
+The TPM will create new data for the sensitive area and compute a TPMT_PUBLIC.unique from the
+sensitive area based on the object type:
+a) For a symmetric key:
+1) If inSensitive.data is the Empty Buffer, a TPM-generated key value is placed in the new object’s
+TPMT_SENSITIVE.sensitive.sym. The size of the key will be determined by
+inPublic.publicArea.parameters.
+2) If inSensitive.data is not the Empty Buffer, the TPM will validate that the size of inSensitive.data is
+no larger than the key size indicated in the inPublic template (TPM_RC_SIZE) and copy the
+inSensitive.data to TPMT_SENSITIVE.sensitive.sym of the new object.
+3) A TPM-generated obfuscation value is placed in TPMT_SENSITIVE.sensitive.seedValue. The
+size of the obfuscation value is the size of the digest produced by the nameAlg in inPublic. This
+value prevents the public unique value from leaking information about the sensitive area.
+4) The TPMT_PUBLIC.unique.sym.buffer value for the new object is then generated, as shown in
+equation (1) below, by hashing the key and obfuscation values in the TPMT_SENSITIVE with the
+nameAlg of the object.
+
+unique ≔ HnameAlg(sensitive.seedValue.buffer || sensitive.any.buffer)
+
+(1)
+
+b) If the Object is an asymmetric key:
+1) If sensitive.data is not the Empty Buffer, then the TPM shall return TPM_RC_VALUE.
+
+Page 46
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+2) A TPM-generated private key value is created with the size determined by the parameters of
+inPublic.publicArea.parameters.
+3) If the key is a Storage Key, a TPM-generated TPMT_SENSITIVE.symKey value is created;
+otherwise, TPMT_SENSITIVE.symKey.size is set to zero.
+4) The public unique value is computed from the private key according to the methods of the key
+type.
+5) If the key is an ECC key and the scheme required by the curveID is not the same as scheme in
+the public area of the template, then the TPM shall return TPM_RC_SCHEME.
+6) If the key is an ECC key and the KDF required by the curveID is not the same as kdf in the pubic
+area of the template, then the TPM shall return TPM_RC_KDF.
+NOTE 1
+
+There is currently no command in which the caller may specify the KDF to be used with an
+ECC decryption key. Since there is no use for this capability, the reference implementation
+requires that the kdf in the template be set to TPM_ALG_NULL or TPM_RC_KDF is
+returned.
+
+c) If the Object is a keyedHash object:
+1) If inSensitive.data is an Empty Buffer, and neither sign nor decrypt is SET in inPublic.attributes,
+the TPM shall return TPM_RC_ATTRIBUTES. This would be a data object with no data.
+2) If inSensitive.data is not an Empty Buffer, the TPM will copy the inSensitive.data to
+TPMT_SENSITIVE.sensitive of the new object.
+NOTE 2
+
+The size of inSensitive.data is limited to be no larger
+TPMT_SENSITIVE.sensitive.bits.data by MAX_SYM_DATA.
+
+than
+
+the
+
+largest
+
+value
+
+of
+
+3) If inSensitive.data is an Empty Buffer, a TPM-generated key value that is the size of the digest
+produced by the nameAlg in inPublic is placed in TPMT_SENSITIVE.sensitive.any.buffer.
+4) A TPM-generated obfuscation value that is the size of the digest produced by the nameAlg of
+inPublic is placed in TPMT_SENSITIVE.symKey.buffer.
+5) The TPMT_PUBLIC.unique.sym.buffer value for the new object is then generated, as shown in
+equation (1) above, by hashing the key and obfuscation values in the TPMT_SENSITIVE with the
+nameAlg of the object.
+For TPM2_Load(), the TPM will apply normal symmetric protections to the created TPMT_SENSITIVE to
+create outPublic.
+NOTE 3
+
+The encryption key is derived from the symmetric seed in the sensitive area of the parent.
+
+In addition to outPublic and outPrivate, the TPM will build a TPMS_CREATION_DATA structure for the
+object. TPMS_CREATION_DATA.outsideInfo is set to outsideInfo. This structure is returned in
+creationData. Additionally, the digest of this structure is returned in creationHash, and, finally, a
+TPMT_TK_CREATION is created so that the association between the creation data and the object may
+be validated by TPM2_CertifyCreation().
+If the object being created is a Storage Key and inPublic.objectAttributes.fixedParent is SET, then the
+algorithms of inPublic are required to match those of the parent. The algorithms that must match are
+inPublic.type, inPublic.nameAlg, and inPublic.parameters. If inPublic.type does not match, the TPM shall
+return TPM_RC_TYPE. If inPublic.nameAlg does not match, the TPM shall return TPM_RC_HASH. If
+inPublic.parameters does not match, the TPM shall return TPM_RC_ASSYMETRIC. The TPM shall not
+differentiate between mismatches of the components of inPublic.parameters.
+EXAMPLE
+
+If the inPublic.parameters.ecc.symmetric.algorithm does not match the parent, the TPM shall return
+TPM_RC_ ASYMMETRIC rather than TPM_RC_SYMMETRIC.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 47
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.1.2 Command and Response
+Table 19 — TPM2_Create Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Create
+
+TPMI_DH_OBJECT
+
+@parentHandle
+
+handle of parent for new object
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_SENSITIVE_CREATE
+
+inSensitive
+
+the sensitive data
+
+TPM2B_PUBLIC
+
+inPublic
+
+the public template
+
+TPM2B_DATA
+
+outsideInfo
+
+data that will be included in the creation data for this
+object to provide permanent, verifiable linkage between
+this object and some object owner data
+
+TPML_PCR_SELECTION
+
+creationPCR
+
+PCR that will be used in creation data
+
+Table 20 — TPM2_Create Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outPrivate
+
+the private portion of the object
+
+TPM2B_PUBLIC
+
+outPublic
+
+the public portion of the created object
+
+TPM2B_CREATION_DATA
+
+creationData
+
+contains a TPMS_CREATION_DATA
+
+TPM2B_DIGEST
+
+creationHash
+
+digest of creationData using nameAlg of outPublic
+
+TPMT_TK_CREATION
+
+creationTicket
+
+ticket used by TPM2_CertifyCreation() to validate that
+the creation data was produced by the TPM
+
+Page 48
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.1.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Object_spt_fp.h"
+#include "Create_fp.h"
+Error Returns
+TPM_RC_ASYMMETRIC
+
+non-duplicable storage key and its parent have different public
+params
+
+TPM_RC_ATTRIBUTES
+
+sensitiveDataOrigin is CLEAR when 'sensitive. data' is an Empty
+Buffer, or is SET when 'sensitive. data' is not empty; fixedTPM,
+fixedParent, or encryptedDuplication attributes are inconsistent
+between themselves or with those of the parent object; inconsistent
+restricted, decrypt and sign attributes; attempt to inject sensitive data
+for an asymmetric key; attempt to create a symmetric cipher key that
+is not a decryption key
+
+TPM_RC_HASH
+
+non-duplicable storage key and its parent have different name
+algorithm
+
+TPM_RC_KDF
+
+incorrect KDF specified for decrypting keyed hash object
+
+TPM_RC_KEY
+
+invalid key size values in an asymmetric key public area
+
+TPM_RC_KEY_SIZE
+
+key size in public area for symmetric key differs from the size in the
+sensitive creation area; may also be returned if the TPM does not
+allow the key size to be used for a Storage Key
+
+TPM_RC_RANGE
+
+FOr() an RSA key, the exponent value is not supported.
+
+TPM_RC_SCHEME
+
+inconsistent attributes decrypt, sign, restricted and key's scheme ID;
+or hash algorithm is inconsistent with the scheme ID for keyed hash
+object
+
+TPM_RC_SIZE
+
+size of public auth policy or sensitive auth value does not match
+digest size of the name algorithm sensitive data size for the keyed
+hash object is larger than is allowed for the scheme
+
+TPM_RC_SYMMETRIC
+
+a storage key with no symmetric algorithm specified; or non-storage
+key with symmetric algorithm different from TPM_ALG_NULL
+
+TPM_RC_TYPE
+
+unknown object type; non-duplicable storage key and its parent have
+different types; parentHandle does not reference a restricted
+decryption key in the storage hierarchy with both public and sensitive
+portion loaded
+
+TPM_RC_VALUE
+
+exponent is not prime or could not find a prime using the provided
+parameters for an RSA key; unsupported name algorithm for an ECC
+key
+
+TPM_RC_OBJECT_MEMORY
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+Meaning
+
+there is no free slot for the object. This implementation does not
+return this error.
+
+TPM_RC
+TPM2_Create(
+Create_In
+Create_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMT_SENSITIVE
+TPM2B_NAME
+
+Family “2.0”
+Level 00 Revision 00.99
+
+result = TPM_RC_SUCCESS;
+sensitive;
+name;
+
+Published
+Copyright © TCG 2006-2013
+
+Page 49
+October 31, 2013
+
+ Part 3: Commands
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
+Trusted Platform Module Library
+
+// Input Validation
+OBJECT
+
+*parentObject;
+
+parentObject = ObjectGet(in->parentHandle);
+// Does parent have the proper attributes?
+if(!AreAttributesForParent(parentObject))
+return TPM_RC_TYPE + RC_Create_parentHandle;
+// The sensitiveDataOrigin attribute must be consistent with the setting of
+// the size of the data object in inSensitive.
+if(
+(in->inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin == SET)
+!= (in->inSensitive.t.sensitive.data.t.size == 0))
+// Mismatch between the object attributes and the parameter.
+return TPM_RC_ATTRIBUTES + RC_Create_inSensitive;
+// Check attributes in input public area. TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES,
+// TPM_RC_HASH, TPM_RC_KDF, TPM_RC_SCHEME, TPM_RC_SIZE, TPM_RC_SYMMETRIC,
+// or TPM_RC_TYPE error may be returned at this point.
+result = PublicAttributesValidation(FALSE, in->parentHandle,
+&in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Create_inPublic);
+// Validate the sensitive area values
+if( MemoryRemoveTrailingZeros(&in->inSensitive.t.sensitive.userAuth)
+> CryptGetHashDigestSize(in->inPublic.t.publicArea.nameAlg))
+return TPM_RC_SIZE + RC_Create_inSensitive;
+// Command Output
+// Create object crypto data
+result = CryptCreateObject(in->parentHandle, &in->inPublic.t.publicArea,
+&in->inSensitive.t.sensitive, &sensitive);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Fill in creation data
+FillInCreationData(in->parentHandle, in->inPublic.t.publicArea.nameAlg,
+&in->creationPCR, &in->outsideInfo,
+&out->creationData, &out->creationHash);
+// Copy public area from input to output
+out->outPublic.t.publicArea = in->inPublic.t.publicArea;
+// Compute name from public area
+ObjectComputeName(&(out->outPublic.t.publicArea), &name);
+// Compute creation ticket
+TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &name,
+&out->creationHash, &out->creationTicket);
+// Prepare output private data from sensitive
+SensitiveToPrivate(&sensitive, &name, in->parentHandle,
+out->outPublic.t.publicArea.nameAlg,
+&out->outPrivate);
+return TPM_RC_SUCCESS;
+}
+
+Page 50
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.2
+
+Part 3: Commands
+
+TPM2_Load
+
+14.2.1 General Description
+This command is used to load objects into the TPM. This command is used when both a TPM2B_PUBLIC
+and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be loaded, the
+TPM2_LoadExternal command is used.
+NOTE 1
+
+Loading an object is not the same as restoring a saved object context.
+
+The object’s TPMA_OBJECT attributes will be checked according to the rules defined in
+“TPMA_OBJECT” in Part 2 of this specification.
+Objects loaded using this command will have a Name. The Name is the concatenation of nameAlg and
+the digest of the public area using the nameAlg.
+NOTE 2
+
+nameAlg is a parameter in the public area of the inPublic structure.
+
+If inPrivate.size is zero, the load will fail.
+After inPrivate.buffer is decrypted using the symmetric key of the parent, the integrity value shall be
+checked before the sensitive area is used, or unmarshaled.
+NOTE 3
+
+Checking the integrity before the data is used prevents attacks o n the sensitive area by fuzzing the
+data and looking at the differences in the response codes.
+
+The command returns a handle for the loaded object and the Name that the TPM computed for
+inPublic.public (that is, the digest of the TPMT_PUBLIC structure in inPublic).
+NOTE 4
+
+The TPM-computed Name is provided as a convenience to the caller for those cases where the
+caller does not implement the hash algorithms specified in the nameAlg of the object.
+
+NOTE 5
+
+The returned handle is associated with the object until the object is flushed (TPM2_FlushContext) or
+until the next TPM2_Startup.
+
+For all objects, the size of the key in the sensitive area shall be consistent with the key size indicated in
+the public area or the TPM shall return TPM_RC_KEY_SIZE.
+Before use, a loaded object shall be checked to validate that the public and sensitive portions are
+properly linked, cryptographically. Use of an object includes use in any policy command. If the parts of the
+object are not properly linked, the TPM shall return TPM_RC_BINDING.
+EXAMPLE 1
+
+For a symmetric object, the unique value in the public area shall be the digest of the sensitive key
+and the obfuscation value.
+
+EXAMPLE 2
+
+For a two-prime RSA key, the remainder when dividing the public modulus by the private key shall
+be zero and it shall be possible to form a private exponent from the two prime factors of the public
+modulus.
+
+EXAMPLE 3
+
+For an ECC key, the public point shall be f(x) where x is the private key.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 51
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.2.2 Command and Response
+Table 21 — TPM2_Load Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Load
+
+TPMI_DH_OBJECT
+
+@parentHandle
+
+TPM handle of parent key; shall not be a reserved
+handle
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_PRIVATE
+
+inPrivate
+
+the private portion of the object
+
+TPM2B_PUBLIC
+
+inPublic
+
+the public portion of the object
+
+Table 22 — TPM2_Load Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM_HANDLE
+
+objectHandle
+
+handle for the loaded object
+
+TPM2B_NAME
+
+name
+
+Name of the loaded object
+
+Page 52
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Load_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ASYMMETRIC
+
+storage key with different asymmetric type than parent
+
+TPM_RC_ATTRIBUTES
+
+inPulblic attributes are not allowed with selected parent
+
+TPM_RC_BINDING
+
+inPrivate and inPublic are not cryptographically bound
+
+TPM_RC_HASH
+
+incorrect hash selection for signing key
+
+TPM_RC_INTEGRITY
+
+HMAC on inPrivate was not valid
+
+TPM_RC_KDF
+
+KDF selection not allowed
+
+TPM_RC_KEY
+
+the size of the object's unique field is not consistent with the indicated
+size in the object's parameters
+
+TPM_RC_OBJECT_MEMORY
+
+no available object slot
+
+TPM_RC_SCHEME
+
+the signing scheme is not valid for the key
+
+TPM_RC_SENSITIVE
+
+the inPrivate did not unmarshal correctly
+
+TPM_RC_SIZE
+
+inPrivate missing, or authPolicy size for inPublic or is not valid
+
+TPM_RC_SYMMETRIC
+
+symmetric algorithm not provided when required
+
+TPM_RC_TYPE
+
+parentHandle is not a storage key, or the object to load is a storage
+key but its parameters do not match the parameters of the parent.
+
+TPM_RC_VALUE
+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
+
+Meaning
+
+decryption failure
+
+TPM_RC
+TPM2_Load(
+Load_In *in,
+Load_Out *out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMT_SENSITIVE
+TPMI_RH_HIERARCHY
+OBJECT
+BOOL
+
+result = TPM_RC_SUCCESS;
+sensitive;
+hierarchy;
+*parentObject = NULL;
+skipChecks = FALSE;
+
+// Input Validation
+if(in->inPrivate.t.size == 0)
+return TPM_RC_SIZE + RC_Load_inPrivate;
+parentObject = ObjectGet(in->parentHandle);
+// Is the object that is being used as the parent actually a parent.
+if(!AreAttributesForParent(parentObject))
+return TPM_RC_TYPE + RC_Load_parentHandle;
+// If the parent is fixedTPM, then the attributes of the object
+// are either "correct by construction" or were validated
+// when the object was imported. If they pass the integrity
+// check, then the values are valid
+if(parentObject->publicArea.objectAttributes.fixedTPM)
+skipChecks = TRUE;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 53
+October 31, 2013
+
+ Part 3: Commands
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+Trusted Platform Module Library
+
+else
+{
+// If parent doesn't have fixedTPM SET, then this can't have
+// fixedTPM SET.
+if(in->inPublic.t.publicArea.objectAttributes.fixedTPM == SET)
+return TPM_RC_ATTRIBUTES + RC_Load_inPublic;
+// Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
+// TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
+// TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
+// at this point
+result = PublicAttributesValidation(TRUE, in->parentHandle,
+&in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Load_inPublic);
+}
+// Compute the name of object
+ObjectComputeName(&in->inPublic.t.publicArea, &out->name);
+// Retrieve sensitive data. PrivateToSensitive() may return TPM_RC_INTEGRITY or
+// TPM_RC_SENSITIVE
+// errors may be returned at this point
+result = PrivateToSensitive(&in->inPrivate, &out->name, in->parentHandle,
+in->inPublic.t.publicArea.nameAlg,
+&sensitive);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Load_inPrivate);
+// Internal Data Update
+// Get hierarchy of parent
+hierarchy = ObjectGetHierarchy(in->parentHandle);
+// Create internal object. A lot of different errors may be returned by this
+// loading operation as it will do several validations, including the public
+// binding check
+result = ObjectLoad(hierarchy, &in->inPublic.t.publicArea, &sensitive,
+&out->name, in->parentHandle, skipChecks,
+&out->objectHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+return TPM_RC_SUCCESS;
+}
+
+Page 54
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.3
+
+Part 3: Commands
+
+TPM2_LoadExternal
+
+14.3.1 General Description
+This command is used to load an object that is not a Protected Object into the TPM. The command allows
+loading of a public area or both a public and sensitive area.
+NOTE 1
+
+Typical use for loading a public area is to allow the TPM to validate an asymmetric signature.
+Typical use for loading both a public and sensitive area is to allow the TPM to be used as a crypto
+accelerator.
+
+Load of a public external object area allows the object be associated with a hierarchy so that the correct
+algorithms may be used when creating tickets. The hierarchy parameter provides this association. If the
+public and sensitive portions of the object are loaded, hierarchy is required to be TPM_RH_NULL.
+NOTE 2
+
+If both the public and private portions of an object are loaded, the object is not allowed to appear to
+be part of a hierarchy.
+
+The object’s TPMA_OBJECT attributes will be checked according to the rules defined in
+“TPMA_OBJECT” in Part 2. In particular, fixedTPM, fixedParent, and restricted shall be CLEAR if
+inPrivate is not the Empty Buffer.
+NOTE 3
+
+The duplication status of a public key needs to be able to be the same as the full key which may be
+resident on a different TPM. If both the public and private parts of the key are loaded, then it is not
+possible for the key to be either fixedTPM or fixedParent, since, its private area would not be
+available in the clear to load.
+
+Objects loaded using this command will have a Name. The Name is the nameAlg of the object
+concatenated with the digest of the public area using the nameAlg. The Qualified Name for the object will
+be the same as its Name. The TPM will validate that the authPolicy is either the size of the digest
+produced by nameAlg or the Empty Buffer.
+NOTE 4
+
+If nameAlg is TPM_ALG_NULL, then the Name is the Empty Buffer. When the authorization value for
+an object with no Name is computed, no Name value is included in the HMAC. To ensure that these
+unnamed entities are not substituted, they should have an authValue that is statistically unique.
+
+NOTE 5
+
+The digest size for TPM_ALG_NULL is zero.
+
+If the nameAlg is TPM_ALG_NULL, the TPM shall not verify the cryptographic binding between the public
+and sensitive areas, but the TPM will validate that the size of the key in the sensitive area is consistent
+with the size indicated in the public area. If it is not, the TPM shall return TPM_RC_KEY_SIZE.
+NOTE 6
+
+For an ECC object, the TPM will verify that the public key is on the curve of the key before the public
+area is used.
+
+If nameAlg is not TPM_ALG_NULL, then the same consistency checks between inPublic and inPrivate
+are made as for TPM2_Load().
+NOTE 7
+
+Consistency checks are necessary because an object with a Name needs to have the public and
+sensitive portions cryptographically bound so that an attacker cannot mix pubic and sensitive areas.
+
+The command returns a handle for the loaded object and the Name that the TPM computed for
+inPublic.public (that is, the TPMT_PUBLIC structure in inPublic).
+NOTE 8
+
+The TPM-computed Name is provided as a convenience to the caller for those cases where the
+caller does not implement the hash algorithm specified in the nameAlg of the object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 55
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+The hierarchy parameter associates the external object with a hierarchy. External objects are flushed
+when their associated hierarchy is disabled. If hierarchy is TPM_RH_NULL, the object is part of no
+hierarchy, and there is no implicit flush.
+If hierarchy is TPM_RH_NULL or nameAlg is TPM_ALG_NULL, a ticket produced using the object shall
+be a NULL Ticket.
+EXAMPLE
+
+If a key is loaded with hierarchy set to TPM_RH_NULL, then TPM2_VerifySignature() will produce a
+NULL Ticket of the required type.
+
+External objects are Temporary Objects. The saved external object contexts shall be invalidated at the
+next TPM Reset.
+
+Page 56
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.3.2 Command and Response
+Table 23 — TPM2_LoadExternal Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_LoadExternal
+
+TPM2B_SENSITIVE
+
+inPrivate
+
+the sensitive portion of the object (optional)
+
+TPM2B_PUBLIC+
+
+inPublic
+
+the public portion of the object
+
+TPMI_RH_HIERARCHY+
+
+hierarchy
+
+hierarchy with which the object area is associated
+
+Table 24 — TPM2_LoadExternal Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM_HANDLE
+
+objectHandle
+
+handle for the loaded object
+
+TPM2B_NAME
+
+name
+
+name of the loaded object
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 57
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "LoadExternal_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+'fixedParent" and fixedTPM must be CLEAR on on an external key if
+both public and sensitive portions are loaded
+
+TPM_RC_BINDING
+
+the inPublic and inPrivate structures are not cryptographically bound.
+
+TPM_RC_HASH
+
+incorrect hash selection for signing key
+
+TPM_RC_HIERARCHY
+
+hierarchy is turned off, or only NULL hierarchy is allowed when
+loading public and private parts of an object
+
+TPM_RC_KDF
+
+incorrect KDF selection for decrypting keyedHash object
+
+TPM_RC_KEY
+
+the size of the object's unique field is not consistent with the indicated
+size in the object's parameters
+
+TPM_RC_OBJECT_MEMORY
+
+if there is no free slot for an object
+
+TPM_RC_SCHEME
+
+the signing scheme is not valid for the key
+
+TPM_RC_SIZE
+
+authPolicy is not zero and is not the size of a digest produced by the
+object's nameAlg TPM_RH_NULL hierarchy
+
+TPM_RC_SYMMETRIC
+
+symmetric algorithm not provided when required
+
+TPM_RC_TYPE
+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
+33
+
+Meaning
+
+inPublic and inPrivate are not the same type
+
+TPM_RC
+TPM2_LoadExternal(
+LoadExternal_In
+LoadExternal_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+TPMT_SENSITIVE
+BOOL
+
+result;
+*sensitive;
+skipChecks;
+
+)
+{
+
+// Input Validation
+// If the target hierarchy is turned off, the object can not be loaded.
+if(!HierarchyIsEnabled(in->hierarchy))
+return TPM_RC_HIERARCHY + RC_LoadExternal_hierarchy;
+// the size of authPolicy is either 0 or the digest size of nameAlg
+if(in->inPublic.t.publicArea.authPolicy.t.size != 0
+&& in->inPublic.t.publicArea.authPolicy.t.size !=
+CryptGetHashDigestSize(in->inPublic.t.publicArea.nameAlg))
+return TPM_RC_SIZE + RC_LoadExternal_inPublic;
+// For loading an object with both public and sensitive
+if(in->inPrivate.t.size != 0)
+{
+// An external object can only be loaded at TPM_RH_NULL hierarchy
+if(in->hierarchy != TPM_RH_NULL)
+return TPM_RC_HIERARCHY + RC_LoadExternal_hierarchy;
+// An external object with a sensitive area must have fixedTPM == CLEAR
+// fixedParent == CLEAR, and must have restrict CLEAR so that it does not
+
+Page 58
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+
+Part 3: Commands
+
+// appear to be a key that was created by this TPM.
+if(
+in->inPublic.t.publicArea.objectAttributes.fixedTPM != CLEAR
+|| in->inPublic.t.publicArea.objectAttributes.fixedParent != CLEAR
+|| in->inPublic.t.publicArea.objectAttributes.restricted != CLEAR
+)
+return TPM_RC_ATTRIBUTES + RC_LoadExternal_inPublic;
+}
+// Validate the scheme parameters
+result = SchemeChecks(TRUE, TPM_RH_NULL, &in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_LoadExternal_inPublic);
+// Internal Data Update
+// Need the name to compute the qualified name
+ObjectComputeName(&in->inPublic.t.publicArea, &out->name);
+skipChecks = (in->inPublic.t.publicArea.nameAlg == TPM_ALG_NULL);
+// If a sensitive area was provided, load it
+if(in->inPrivate.t.size != 0)
+sensitive = &in->inPrivate.t.sensitiveArea;
+else
+sensitive = NULL;
+// Create external object. A TPM_RC_BINDING, TPM_RC_KEY, TPM_RC_OBJECT_MEMORY
+// or TPM_RC_TYPE error may be returned by ObjectLoad()
+result = ObjectLoad(in->hierarchy, &in->inPublic.t.publicArea,
+sensitive, &out->name, TPM_RH_NULL, skipChecks,
+&out->objectHandle);
+return result;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 59
+October 31, 2013
+
+ Part 3: Commands
+
+14.4
+
+Trusted Platform Module Library
+
+TPM2_ReadPublic
+
+14.4.1 General Description
+This command allows access to the public area of a loaded object.
+Use of the objectHandle does not require authorization.
+NOTE
+
+Since the caller is not likely to know the public area of the object associated with objectHandle, it
+would not be possible to include the Name associated with objectHandle in the cpHash computation.
+
+If objectHandle references a sequence object, the TPM shall return TPM_RC_SEQUENCE.
+
+Page 60
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.4.2 Command and Response
+Table 25 — TPM2_ReadPublic Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ReadPublic
+
+TPMI_DH_OBJECT
+
+objectHandle
+
+TPM handle of an object
+Auth Index: None
+
+Table 26 — TPM2_ReadPublic Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PUBLIC
+
+outPublic
+
+structure containing the public area of an object
+
+TPM2B_NAME
+
+name
+
+name of the object
+
+TPM2B_NAME
+
+qualifiedName
+
+the Qualified Name of the object
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 61
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "ReadPublic_fp.h"
+Error Returns
+TPM_RC_SEQUENCE
+
+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
+33
+34
+35
+36
+
+Meaning
+can not read the public area of a sequence object
+
+TPM_RC
+TPM2_ReadPublic(
+ReadPublic_In
+ReadPublic_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+OBJECT
+
+*object;
+
+)
+{
+// Input Validation
+// Get loaded object pointer
+object = ObjectGet(in->objectHandle);
+// Can not read public area of a sequence object
+if(ObjectIsSequence(object))
+return TPM_RC_SEQUENCE;
+// Command Output
+// Compute size of public area in canonical form
+out->outPublic.t.size = TPMT_PUBLIC_Marshal(&object->publicArea, NULL, NULL);
+// Copy public area to output
+out->outPublic.t.publicArea = object->publicArea;
+// Copy name to output
+out->name.t.size = ObjectGetName(in->objectHandle, &out->name.t.name);
+// Copy qualified name to output
+ObjectGetQualifiedName(in->objectHandle, &out->qualifiedName);
+return TPM_RC_SUCCESS;
+}
+
+Page 62
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.5
+
+Part 3: Commands
+
+TPM2_ActivateCredential
+
+14.5.1 General Description
+This command enables the association of a credential with an object in a way that ensures that the TPM
+has validated the parameters of the credentialed object.
+If both the public and private portions of activateHandle and keyHandle are not loaded, then the TPM
+shall return TPM_RC_AUTH_UNAVAILABLE.
+If keyHandle is not a Storage Key, then the TPM shall return TPM_RC_TYPE.
+Authorization for activateHandle requires the ADMIN role.
+The key associated with keyHandle is used to recover a seed from secret, which is the encrypted seed.
+The Name of the object associated with activateHandle and the recovered seed are used in a KDF to
+recover the symmetric key. The recovered seed (but not the Name) is used is used in a KDF to recover
+the HMAC key.
+The HMAC is used to validate that the credentialBlob is associated with activateHandle and that the data
+in credentialBlob has not been modified. The linkage to the object associated with activateHandle is
+achieved by including the Name in the HMAC calculation.
+If the integrity checks succeed, credentialBlob is decrypted and returned as certInfo.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 63
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.5.2 Command and Response
+Table 27 — TPM2_ActivateCredential Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPMI_DH_OBJECT
+
+Description
+
+TPM_CC_ActivateCredential
+
+@activateHandle
+
+handle of the object associated with certificate in
+credentialBlob
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+loaded key used to decrypt the TPMS_SENSITIVE in
+credentialBlob
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_ID_OBJECT
+
+credentialBlob
+
+the credential
+
+TPM2B_ENCRYPTED_SECRET
+
+secret
+
+keyHandle algorithm-dependent encrypted seed that
+protects credentialBlob
+
+Table 28 — TPM2_ActivateCredential Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+certInfo
+
+Page 64
+October 31, 2013
+
+the decrypted certificate information
+the data should be no larger than the size of the digest
+of the nameAlg associated with keyHandle
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ActivateCredential_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+keyHandle does not reference a decryption key
+
+TPM_RC_ECC_POINT
+
+secret is invalid (when keyHandle is an ECC key)
+
+TPM_RC_INSUFFICIENT
+
+secret is invalid (when keyHandle is an ECC key)
+
+TPM_RC_INTEGRITY
+
+credentialBlob fails integrity test
+
+TPM_RC_NO_RESULT
+
+secret is invalid (when keyHandle is an ECC key)
+
+TPM_RC_SIZE
+
+secret size is invalid or the credentialBlob does not unmarshal
+correctly
+
+TPM_RC_TYPE
+
+keyHandle does not reference an asymmetric key.
+
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+
+Meaning
+
+secret is invalid (when keyHandle is an RSA key)
+
+TPM_RC
+TPM2_ActivateCredential(
+ActivateCredential_In
+ActivateCredential_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+OBJECT
+// credential
+TPM2B_DATA
+
+result = TPM_RC_SUCCESS;
+*object;
+// decrypt key
+*activateObject;// key associated with
+
+)
+{
+
+data;
+
+// credential data
+
+// Input Validation
+// Get decrypt key pointer
+object = ObjectGet(in->keyHandle);
+// Get certificated object pointer
+activateObject = ObjectGet(in->activateHandle);
+// input decrypt key must be an asymmetric, restricted decryption key
+if(
+!CryptIsAsymAlgorithm(object->publicArea.type)
+|| object->publicArea.objectAttributes.decrypt == CLEAR
+|| object->publicArea.objectAttributes.restricted == CLEAR)
+return TPM_RC_TYPE + RC_ActivateCredential_keyHandle;
+// Command output
+// Decrypt input credential data via asymmetric decryption. A
+// TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
+// point
+result = CryptSecretDecrypt(in->keyHandle, NULL,
+"IDENTITY", &in->secret, &data);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_FAILURE;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 65
+October 31, 2013
+
+ Part 3: Commands
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+Trusted Platform Module Library
+
+return RcSafeAddToResult(result, RC_ActivateCredential_secret);
+}
+// Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal
+// errors may be returned at this point
+result = CredentialToSecret(&in->credentialBlob,
+&activateObject->name,
+(TPM2B_SEED *) &data,
+in->keyHandle,
+&out->certInfo);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result,RC_ActivateCredential_credentialBlob);
+return TPM_RC_SUCCESS;
+}
+
+Page 66
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.6
+
+Part 3: Commands
+
+TPM2_MakeCredential
+
+14.6.1 General Description
+This command allows the TPM to perform the actions required of a Certificate Authority (CA) in creating a
+TPM2B_ID_OBJECT containing an activation credential.
+The TPM will produce a TPM_ID_OBJECT according to the methods in “Credential Protection” in Part 1.
+The loaded public area referenced by handle is required to be the public area of a Storage key,
+otherwise, the credential cannot be properly sealed.
+This command does not use any TPM secrets nor does it require authorization. It is a convenience
+function, using the TPM to perform cryptographic calculations that could be done externally.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 67
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.6.2 Command and Response
+Table 29 — TPM2_MakeCredential Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_MakeCredential
+
+TPMI_DH_OBJECT
+
+handle
+
+loaded public area, used to encrypt the sensitive area
+containing the credential key
+Auth Index: None
+
+TPM2B_DIGEST
+
+credential
+
+the credential information
+
+TPM2B_NAME
+
+objectName
+
+Name of the object to which the credential applies
+
+Table 30 — TPM2_MakeCredential Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ID_OBJECT
+
+credentialBlob
+
+TPM2B_ENCRYPTED_SECRET secret
+
+Page 68
+October 31, 2013
+
+the credential
+handle algorithm-dependent data that wraps the key
+that encrypts credentialBlob
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "MakeCredential_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_KEY
+
+handle referenced an ECC key that has a unique field that is not a
+point on the curve of the key
+
+TPM_RC_SIZE
+
+credential is larger than the digest size of Name algorithm of handle
+
+TPM_RC_TYPE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
+Meaning
+
+handle does not reference an asymmetric decryption key
+
+TPM_RC
+TPM2_MakeCredential(
+MakeCredential_In
+MakeCredential_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+
+result = TPM_RC_SUCCESS;
+
+OBJECT
+TPM2B_DATA
+
+*object;
+data;
+
+)
+{
+
+// Input Validation
+// Get object pointer
+object = ObjectGet(in->handle);
+// input key must be an asymmetric, restricted decryption key
+// NOTE: Needs to be restricted to have a symmetric value.
+if(
+!CryptIsAsymAlgorithm(object->publicArea.type)
+|| object->publicArea.objectAttributes.decrypt == CLEAR
+|| object->publicArea.objectAttributes.restricted == CLEAR
+)
+return TPM_RC_TYPE + RC_MakeCredential_handle;
+// The credential information may not be larger than the digest size used for
+// the Name of the key associated with handle.
+if(in->credential.t.size > CryptGetHashDigestSize(object->publicArea.nameAlg))
+return TPM_RC_SIZE + RC_MakeCredential_credential;
+// Command Output
+// Make encrypt key and its associated secret structure.
+// Even though CrypeSecretEncrypt() may return
+out->secret.t.size = sizeof(out->secret.t.secret);
+result = CryptSecretEncrypt(in->handle, "IDENTITY", &data, &out->secret);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Prepare output credential data from secret
+SecretToCredential(&in->credential, &in->objectName, (TPM2B_SEED *) &data,
+in->handle, &out->credentialBlob);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 69
+October 31, 2013
+
+ Part 3: Commands
+
+14.7
+
+Trusted Platform Module Library
+
+TPM2_Unseal
+
+14.7.1 General Description
+This command returns the data in a loaded Sealed Data Object.
+NOTE
+
+A random, TPM-generated, Sealed Data Object may be created by the TPM with TPM2_Create() or
+TPM2_CreatePrimary() using the template for a Sealed Data Object. A Sealed Data Object is more
+likely to be created externally and imported (TPM2_Import()) so that the data is not created by the
+TPM.
+
+The returned value may be encrypted using authorization session encryption.
+If either restricted, decrypt, or sign is SET in the attributes of itemHandle, then the TPM shall return
+TPM_RC_ATTRIBUTES. If the type of itemHandle is not TPM_ALG_KEYEDHASH, then the TPM shall
+return TPM_RC_TYPE.
+
+Page 70
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.7.2 Command and Response
+Table 31 — TPM2_Unseal Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+Tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Unseal
+
+@itemHandle
+
+handle of a loaded data object
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+Description
+
+Table 32 — TPM2_Unseal Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_SENSITIVE_DATA
+
+outData
+
+Family “2.0”
+Level 00 Revision 00.99
+
+unsealed data
+Size of outData is limited to be no more than 128 octets.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 71
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Unseal_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+itemHandle has wrong attributes
+
+TPM_RC_TYPE
+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
+
+Meaning
+
+itemHandle is not a KEYEDHASH data object
+
+TPM_RC
+TPM2_Unseal(Unseal_In *in, Unseal_Out *out)
+{
+OBJECT
+
+*object;
+
+// Input Validation
+// Get pointer to loaded object
+object = ObjectGet(in->itemHandle);
+// Input handle must be a data object
+if(object->publicArea.type != TPM_ALG_KEYEDHASH)
+return TPM_RC_TYPE + RC_Unseal_itemHandle;
+if(
+object->publicArea.objectAttributes.decrypt == SET
+|| object->publicArea.objectAttributes.sign == SET
+|| object->publicArea.objectAttributes.restricted == SET)
+return TPM_RC_ATTRIBUTES + RC_Unseal_itemHandle;
+// Command Output
+// Copy data
+MemoryCopy2B(&out->outData.b, &object->sensitive.sensitive.bits.b,
+sizeof(out->outData.t.buffer));
+return TPM_RC_SUCCESS;
+}
+
+Page 72
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.8
+
+Part 3: Commands
+
+TPM2_ObjectChangeAuth
+
+14.8.1 General Description
+This command is used to change the authorization secret for a TPM-resident object.
+If successful, a new private area for the TPM-resident object associated with objectHandle is returned,
+which includes the new authorization value.
+This command does not change the authorization of the TPM-resident object on which it operates.
+Therefore, the old authValue (of the TPM-resident object) is used when generating the response HMAC
+key if required..
+NOTE 1
+
+The returned outPrivate will need to be loaded before the new authorization will apply.
+
+NOTE 2
+
+The TPM-resident object may be persistent and changing the authorization value of the persistent
+object could prevent other users from accessing the object. This is why this command does not
+change the TPM-resident object.
+
+EXAMPLE
+
+If a persistent key is being used as a Storage Root Key and the authorization of the key is a well known value so that the key can be used generally, then changing the authorization value in the
+persistent key would deny access to other users.
+
+This command may not be used to change the authorization value for an NV Index or a Primary Object.
+NOTE 3
+
+If an NV Index is to have a new authorization, it is done with TPM2_NV_ChangeAuth().
+
+NOTE 4
+
+If a Primary Object is to have a new authorization, it needs to be recreated (TPM2_CreatePrimary()).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 73
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.8.2 Command and Response
+Table 33 — TPM2_ObjectChangeAuth Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ObjectChangeAuth
+
+TPMI_DH_OBJECT
+
+@objectHandle
+
+handle of the object
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT
+
+parentHandle
+
+handle of the parent
+Auth Index: None
+
+TPM2B_AUTH
+
+newAuth
+
+new authorization value
+
+Table 34 — TPM2_ObjectChangeAuth Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outPrivate
+
+Page 74
+October 31, 2013
+
+private area containing the new authorization value
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.8.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ObjectChangeAuth_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+newAuth is larger than the size of the digest of the Name algorithm of
+objectHandle
+
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+the key referenced by parentHandle is not the parent of the object
+referenced by objectHandle; or objectHandle is a sequence object.
+
+TPM_RC
+TPM2_ObjectChangeAuth(
+ObjectChangeAuth_In
+ObjectChangeAuth_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPMT_SENSITIVE
+OBJECT
+TPM2B_NAME
+TPM2B_NAME
+
+sensitive;
+*object;
+objectQN, QNCompare;
+parentQN;
+
+// Input Validation
+// Get object pointer
+object = ObjectGet(in->objectHandle);
+// Can not change auth on sequence object
+if(ObjectIsSequence(object))
+return TPM_RC_TYPE + RC_ObjectChangeAuth_objectHandle;
+// Make sure that the auth value is consistent with the nameAlg
+if( MemoryRemoveTrailingZeros(&in->newAuth)
+> CryptGetHashDigestSize(object->publicArea.nameAlg))
+return TPM_RC_SIZE + RC_ObjectChangeAuth_newAuth;
+// Check parent for object
+// parent handle must be the parent of object handle. In this
+// implementation we verify this by checking the QN of object. Other
+// implementation may choose different method to verify this attribute.
+ObjectGetQualifiedName(in->parentHandle, &parentQN);
+ObjectComputeQualifiedName(&parentQN, object->publicArea.nameAlg,
+&object->name, &QNCompare);
+ObjectGetQualifiedName(in->objectHandle, &objectQN);
+if(!Memory2BEqual(&objectQN.b, &QNCompare.b))
+return TPM_RC_TYPE + RC_ObjectChangeAuth_parentHandle;
+// Command Output
+// Copy internal sensitive area
+sensitive = object->sensitive;
+// Copy authValue
+sensitive.authValue = in->newAuth;
+// Prepare output private data from sensitive
+SensitiveToPrivate(&sensitive, &object->name, in->parentHandle,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 75
+October 31, 2013
+
+ Part 3: Commands
+52
+53
+54
+55
+56
+
+Trusted Platform Module Library
+object->publicArea.nameAlg,
+&out->outPrivate);
+
+return TPM_RC_SUCCESS;
+}
+
+Page 76
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+15
+
+Part 3: Commands
+
+Duplication Commands
+
+15.1
+
+TPM2_Duplicate
+
+15.1.1 General Description
+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 TPM_RH_NULL. Only the public area of
+newParentHandle is required to be loaded.
+NOTE 1
+
+Since the new parent may only be extant on a different TPM, it is likely that the new parent’s
+sensitive area could not be loaded in the TPM from which objectHandle is being duplicated.
+
+If encryptedDuplication is SET in the object being duplicated, then the TPM shall return
+TPM_RC_SYMMETRIC if symmetricAlg is TPM_RH_NULL or TPM_RC_HIERARCHY if
+newParentHandle is TPM_RH_NULL.
+The authorization for this command shall be with a policy session.
+If fixedParent of objectHandle→attributes is SET, the TPM shall return TPM_RC_ATTRIBUTES. If
+objectHandle→nameAlg is TPM_ALG_NULL, the TPM shall return TPM_RC_TYPE.
+The policySession→commandCode parameter in the policy session is required to be TPM_CC_Duplicate
+to indicate that authorization for duplication has been provided. This indicates that the policy that is being
+used is a policy that is for duplication, and not a policy that would approve another use. That is, authority
+to use an object does not grant authority to duplicate the object.
+The policy is likely to include cpHash in order to restrict where duplication can occur.
+If
+TPM2_PolicyCpHash() has been executed as part of the policy, the policySession→cpHash is compared
+to the cpHash of the command.
+If TPM2_PolicyDuplicationSelect() has
+policySession→nameHash is compared to
+
+been
+
+executed
+
+as
+
+part
+
+of
+
+the
+
+policy,
+
+HpolicyAlg(objectHandle→Name || newParentHandle→Name)
+
+the
+(2)
+
+If the compared hashes are not the same, then the TPM shall return TPM_RC_POLICY_FAIL.
+NOTE 2
+
+It is allowed that policySesion→nameHash and policySession→cpHash share the same memory
+space.
+
+NOTE 3
+
+A duplication policy is not required to have either TPM2_PolicyDuplicationSelect() or
+TPM2_PolicyCpHash() as part of the policy. If neither is present, then the duplication policy may be
+satisfied with a policy that only contains TPM2_PolicyCommaneCode( code = TPM_CC_Duplicate).
+
+The TPM shall follow the process of encryption defined in the “Duplication” subclause of “Protected
+Storage Hierarchy” in Part 1 of this specification.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 77
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+15.1.2 Command and Response
+Table 35 — TPM2_Duplicate Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Duplicate
+
+TPMI_DH_OBJECT
+
+@objectHandle
+
+loaded object to duplicate
+Auth Index: 1
+Auth Role: DUP
+
+TPMI_DH_OBJECT+
+
+newParentHandle
+
+shall reference the public area of an asymmetric key
+Auth Index: None
+
+TPM2B_DATA
+
+encryptionKeyIn
+
+optional symmetric encryption key
+The size for this key is set to zero when the TPM is to
+generate the key. This parameter may be encrypted.
+
+TPMT_SYM_DEF_OBJECT+
+
+symmetricAlg
+
+definition for the symmetric algorithm to be used for the
+inner wrapper
+may be TPM_ALG_NULL if no inner wrapper is applied
+
+Table 36 — TPM2_Duplicate Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DATA
+
+encryptionKeyOut
+
+If the caller provided an encryption key or if
+symmetricAlg was TPM_ALG_NULL, then this will be
+the Empty Buffer; otherwise, it shall contain the TPMgenerated, symmetric encryption key for the inner
+wrapper.
+
+TPM2B_PRIVATE
+
+duplicate
+
+private area that may be encrypted by encryptionKeyIn;
+and may be doubly encrypted
+
+TPM2B_ENCRYPTED_SECRET outSymSeed
+
+Page 78
+October 31, 2013
+
+seed protected by the asymmetric algorithms of new
+parent (NP)
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+15.1.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Duplicate_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key to duplicate has fixedParent SET
+
+TPM_RC_HIERARCHY
+
+encryptedDuplication is SET and newParentHandle specifies Null
+Hierarchy
+
+TPM_RC_KEY
+
+newParentHandle references invalid ECC key (public point not on the
+curve)
+
+TPM_RC_SIZE
+
+input encryption key size does not match the size specified in
+symmetric algorithm
+
+TPM_RC_SYMMETRIC
+
+encryptedDuplication is SET but no symmetric algorithm is provided
+
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
+Meaning
+
+newParentHandle is neither a storage key nor TPM_RH_NULL; or
+the object has a NULL nameAlg
+
+TPM_RC
+TPM2_Duplicate(
+Duplicate_In
+Duplicate_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMT_SENSITIVE
+
+result = TPM_RC_SUCCESS;
+sensitive;
+
+UINT16
+
+innerKeySize = 0; // encrypt key size for inner wrap
+
+OBJECT
+TPM2B_DATA
+
+*object;
+data;
+
+// Input Validation
+// Get duplicate object pointer
+object = ObjectGet(in->objectHandle);
+// duplicate key must have fixParent bit CLEAR.
+if(object->publicArea.objectAttributes.fixedParent == SET)
+return TPM_RC_ATTRIBUTES + RC_Duplicate_objectHandle;
+// Do not duplicate object with NULL nameAlg
+if(object->publicArea.nameAlg == TPM_ALG_NULL)
+return TPM_RC_TYPE + RC_Duplicate_objectHandle;
+// new parent key must be a storage object or TPM_RH_NULL
+if(in->newParentHandle != TPM_RH_NULL
+&& !ObjectIsStorage(in->newParentHandle))
+return TPM_RC_TYPE + RC_Duplicate_newParentHandle;
+// If the duplicates object has encryptedDuplication SET, then there must be
+// an inner wrapper and the new parent may not be TPM_RH_NULL
+if(object->publicArea.objectAttributes.encryptedDuplication == SET)
+{
+if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
+return TPM_RC_SYMMETRIC + RC_Duplicate_symmetricAlg;
+if(in->newParentHandle == TPM_RH_NULL)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 79
+October 31, 2013
+
+ Part 3: Commands
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+
+Trusted Platform Module Library
+
+return TPM_RC_HIERARCHY + RC_Duplicate_newParentHandle;
+}
+if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
+{
+// if algorithm is TPM_ALG_NULL, input key size must be 0
+if(in->encryptionKeyIn.t.size != 0)
+return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
+}
+else
+{
+// Get inner wrap key size
+innerKeySize = in->symmetricAlg.keyBits.sym;
+// If provided the input symmetric key must match the size of the algorithm
+if(in->encryptionKeyIn.t.size != 0
+&& in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
+return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
+}
+// Command Output
+if(in->newParentHandle != TPM_RH_NULL)
+{
+// Make encrypt key and its associated secret structure. A TPM_RC_KEY
+// error may be returned at this point
+out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
+result = CryptSecretEncrypt(in->newParentHandle,
+"DUPLICATE", &data, &out->outSymSeed);
+pAssert(result != TPM_RC_VALUE);
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+else
+{
+// Do not apply outer wrapper
+data.t.size = 0;
+out->outSymSeed.t.size = 0;
+}
+// Copy sensitive area
+sensitive = object->sensitive;
+// Prepare output private data from sensitive
+SensitiveToDuplicate(&sensitive, &object->name, in->newParentHandle,
+object->publicArea.nameAlg, (TPM2B_SEED *) &data,
+&in->symmetricAlg, &in->encryptionKeyIn,
+&out->duplicate);
+out->encryptionKeyOut = in->encryptionKeyIn;
+return TPM_RC_SUCCESS;
+}
+
+Page 80
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+15.2
+
+Part 3: Commands
+
+TPM2_Rewrap
+
+15.2.1 General Description
+This command allows the TPM to serve in the role as a Duplication Authority. If proper authorization for
+use of the oldParent is provided, then an HMAC key and a symmetric key are recovered from inSymSeed
+and used to integrity check and decrypt inDuplicate. A new protection seed value is generated according
+to the methods appropriate for newParent and the blob is re-encrypted and a new integrity value is
+computed. The re-encrypted blob is returned in outDuplicate and the symmetric key returned in
+outSymKey.
+In the rewrap process, L is “DUPLICATE” (see “Terms and Definitions” in Part 1).
+If inSymSeed has a zero length, then oldParent is required to be TPM_RH_NULL and no decryption of
+inDuplicate takes place.
+If newParent is TPM_RH_NULL, then no encryption is performed on outDuplicate. outSymSeed will have
+a zero length. See Part 2 encryptedDuplication.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 81
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+15.2.2 Command and Response
+Table 37 — TPM2_Rewrap Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Rewrap
+
+TPMI_DH_OBJECT+
+
+@oldParent
+
+parent of object
+Auth Index: 1
+Auth Role: User
+
+TPMI_DH_OBJECT+
+
+newParent
+
+new parent of the object
+Auth Index: None
+
+TPM2B_PRIVATE
+
+inDuplicate
+
+an object encrypted using symmetric key derived from
+inSymSeed
+
+TPM2B_NAME
+
+name
+
+the Name of the object being rewrapped
+
+TPM2B_ENCRYPTED_SECRET inSymSeed
+
+Description
+
+seed for symmetric key
+needs oldParent private key to recover the seed and
+generate the symmetric key
+
+Table 38 — TPM2_Rewrap Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outDuplicate
+
+TPM2B_ENCRYPTED_SECRET outSymSeed
+
+Page 82
+October 31, 2013
+
+an object encrypted using symmetric key derived from
+outSymSeed
+seed for a symmetric key protected by newParent
+asymmetric key
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+15.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Rewrap_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+newParent is not a decryption key
+
+TPM_RC_HANDLE
+
+oldParent does not consistent with inSymSeed
+
+TPM_RC_INTEGRITY
+
+the integrity check of inDuplicate failed
+
+TPM_RC_KEY
+
+for an ECC key, the public key is not on the curve of the curve ID
+
+TPM_RC_KEY_SIZE
+
+the decrypted input symmetric key size does not matches the
+symmetric algorithm key size of oldParent
+
+TPM_RC_TYPE
+
+oldParent is not a storage key, or 'newParent is not a storage key
+
+TPM_RC_VALUE
+
+for an 'oldParent; RSA key, the data to be decrypted is greater than
+the public exponent
+
+Unmarshal errors
+
+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
+33
+34
+35
+36
+37
+38
+39
+
+Meaning
+
+errors during unmarshaling the input encrypted buffer to a ECC public
+key, or unmarshal the private buffer to sensitive
+
+TPM_RC
+TPM2_Rewrap(
+Rewrap_In
+Rewrap_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+TPM2B_DATA
+UINT16
+TPM2B_PRIVATE
+
+result = TPM_RC_SUCCESS;
+*oldParent;
+data;
+// symmetric key
+hashSize = 0;
+privateBlob;
+// A temporary private blob
+// to transit between old
+// and new wrappers
+
+)
+{
+
+// Input Validation
+if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL)
+|| (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL))
+return TPM_RC_HANDLE + RC_Rewrap_oldParent;
+if(in->oldParent != TPM_RH_NULL)
+{
+// Get old parent pointer
+oldParent = ObjectGet(in->oldParent);
+// old parent key must be a storage object
+if(!ObjectIsStorage(in->oldParent))
+return TPM_RC_TYPE + RC_Rewrap_oldParent;
+// Decrypt input secret data via asymmetric decryption. A
+// TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
+// point
+result = CryptSecretDecrypt(in->oldParent, NULL,
+"DUPLICATE", &in->inSymSeed, &data);
+if(result != TPM_RC_SUCCESS)
+return TPM_RC_VALUE + RC_Rewrap_inSymSeed;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 83
+October 31, 2013
+
+ Part 3: Commands
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
+Trusted Platform Module Library
+
+// Unwrap Outer
+result = UnwrapOuter(in->oldParent, &in->name,
+oldParent->publicArea.nameAlg, (TPM2B_SEED *) &data,
+FALSE,
+in->inDuplicate.t.size, in->inDuplicate.t.buffer);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Rewrap_inDuplicate);
+// Copy unwrapped data to temporary variable, remove the integrity field
+hashSize = sizeof(UINT16) +
+CryptGetHashDigestSize(oldParent->publicArea.nameAlg);
+privateBlob.t.size = in->inDuplicate.t.size - hashSize;
+MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize,
+privateBlob.t.size, sizeof(privateBlob.t.buffer));
+}
+else
+{
+// No outer wrap from input blob.
+privateBlob = in->inDuplicate;
+}
+
+Direct copy.
+
+if(in->newParent != TPM_RH_NULL)
+{
+OBJECT
+*newParent;
+newParent = ObjectGet(in->newParent);
+// New parent must be a storage object
+if(!ObjectIsStorage(in->newParent))
+return TPM_RC_TYPE + RC_Rewrap_newParent;
+// Make new encrypt key and its associated secret structure. A
+// TPM_RC_VALUE error may be returned at this point if RSA algorithm is
+// enabled in TPM
+out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
+result = CryptSecretEncrypt(in->newParent,
+"DUPLICATE", &data, &out->outSymSeed);
+if(result != TPM_RC_SUCCESS) return result;
+// Command output
+// Copy temporary variable to output, reserve the space for integrity
+hashSize = sizeof(UINT16) +
+CryptGetHashDigestSize(newParent->publicArea.nameAlg);
+out->outDuplicate.t.size = privateBlob.t.size;
+MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer,
+privateBlob.t.size, sizeof(out->outDuplicate.t.buffer));
+// Produce outer wrapper for output
+out->outDuplicate.t.size = ProduceOuterWrap(in->newParent, &in->name,
+newParent->publicArea.nameAlg,
+(TPM2B_SEED *) &data,
+FALSE,
+out->outDuplicate.t.size,
+out->outDuplicate.t.buffer);
+}
+else // New parent is a null key so there is no seed
+{
+out->outSymSeed.t.size = 0;
+// Copy privateBlob directly
+out->outDuplicate = privateBlob;
+}
+
+Page 84
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+104
+105
+
+Part 3: Commands
+
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 85
+October 31, 2013
+
+ Part 3: Commands
+
+15.3
+
+Trusted Platform Module Library
+
+TPM2_Import
+
+15.3.1 General Description
+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.
+If fixedTPM or fixedParent is SET in objectPublic, the TPM shall return TPM_RC_ATTRIBUTES.
+If encryptedDuplication is SET in the object referenced by parentHandle, then encryptedDuplication shall
+be set in objectPublic (TPM_RC_ATTRIBUTES). However, see Note 2.
+Recovery of the sensitive data of the object occurs in the TPM in a three-step process in the following
+order:
+
+
+If present, the outer layer of symmetric encryption is removed. If inSymSeed has a non-zero size, the
+asymmetric parameters and private key of parentHandle are used to recover the seed used in the
+creation of the HMAC key and encryption keys used to protect the duplication blob. When recovering
+the seed, L is “DUPLICATE”.
+NOTE 1
+
+If the encryptedDuplication attribute of the object
+TPM_RC_ATTRIBUTES if inSymSeed is an empty buffer.
+
+is
+
+SET,
+
+the
+
+TPM
+
+shall
+
+return
+
+
+
+If present, the inner layer of symmetric encryption is removed. If encryptionKey and symmetricAlg are
+provided, they are used to decrypt duplication.
+
+
+
+If present, the integrity value of the blob is checked. The presence of the integrity value is indicated
+by a non-zero value for duplicate.data.integrity.size. The integrity of the private area is validated using
+the Name of objectPublic in the integrity HMAC computation. If either the outer layer or inner layer of
+encryption is performed, then the integrity value shall be present.
+
+If the inner or outer wrapper is present, then a valid integrity value shall be present or the TPM shall
+return TPM_RC_INTEGRITY.
+NOTE 2
+
+It is not necessary to validate that the sensitive area data is cryptographically bound to the public
+area other than that the Name of the public area is included in the HMAC. However, if the binding is
+not validated by this command, the binding must be checked each time the object is loaded. For an
+object that is imported under a parent with fixedTPM SET, binding need only be checked at import. If
+the parent has fixedTPM CLEAR, then the binding needs to be checked each time the object is
+loaded, or before the TPM performs an operation for which the binding affects the outcome of the
+operation (for example, TPM2_PolicySigned() or TPM2_Certify()).
+Similarly, if the new parent's fixedTPM is set, the encryptedDuplication state need only be checked
+at import.
+If the new parent is not fixedTPM, then that object will be loadable on any TPM (including SW
+versions) on which the new parent exists. This means that, each time an object is loaded under a
+parent that is not fixedTPM, it is necessary to validate all of the properties of that object. If the
+parent is fixedTPM, then the new private blob is integrity protected by the TPM that “owns” the
+parent. So, it is sufficient to validate the object’s properties (attribute and public -private binding) on
+import and not again.
+
+Before duplicate.buffer is decrypted using the symmetric key of the parent, the integrity value shall be
+checked before the sensitive area is used, or unmarshaled.
+After integrity checks and decryption, the TPM will create a new symmetrically encrypted private area
+using the encryption key of the parent.
+NOTE 3
+
+Checking the integrity before the data is used prevents attacks on the sensitive area by fuzzing the
+data and looking at the differences in the response codes.
+
+Page 86
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+NOTE 4
+
+Part 3: Commands
+
+The symmetric re-encryption is the normal integrity generation and symmetric encryption applied to
+a child object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 87
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+15.3.2 Command and Response
+Table 39 — TPM2_Import Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Import
+
+TPMI_DH_OBJECT
+
+@parentHandle
+
+the handle of the new parent for the object
+Auth Index: 1
+Auth Role: USER
+
+encryptionKey
+
+the optional symmetric encryption key used as the inner
+wrapper for duplicate
+If symmetricAlg is TPM_ALG_NULL, then this
+parameter shall be the Empty Buffer.
+
+TPM2B_DATA
+
+TPM2B_PUBLIC
+
+objectPublic
+
+Description
+
+the public area of the object to be imported
+This is provided so that the integrity value for duplicate
+and the object attributes can be checked.
+NOTE
+
+TPM2B_PRIVATE
+
+duplicate
+
+Even if the integrity value of the object is not
+checked on input, the object Name is required to
+create the integrity value for the imported object.
+
+the symmetrically encrypted duplicate object that may
+contain an inner symmetric wrapper
+
+TPM2B_ENCRYPTED_SECRET inSymSeed
+
+symmetric key used to encrypt duplicate
+inSymSeed is encrypted/encoded using the algorithms
+of newParent.
+
+TPMT_SYM_DEF_OBJECT+
+
+definition for the symmetric algorithm to use for the inner
+wrapper
+If this algorithm is TPM_ALG_NULL, no inner wrapper is
+present and encryptionKey shall be the Empty Buffer.
+
+symmetricAlg
+
+Table 40 — TPM2_Import Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outPrivate
+
+Page 88
+October 31, 2013
+
+the sensitive area encrypted with the symmetric key of
+parentHandle
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+15.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Import_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+
+Meaning
+
+TPM_RC_ASYMMETRIC
+
+non-duplicable storage key represented by objectPublic and its
+parent referenced by parentHandle have different public params
+
+TPM_RC_ATTRIBUTES
+
+attributes FixedTPM and fixedParent of objectPublic are not both
+CLEAR; or inSymSeed is nonempty and parentHandle does not
+reference a decryption key; or objectPublic and parentHandle have
+incompatible or inconsistent attributes
+
+TPM_RC_BINDING
+
+duplicate and objectPublic are not cryptographically bound
+
+TPM_RC_ECC_POINT
+
+inSymSeed is nonempty and ECC point in inSymSeed is not on the
+curve
+
+TPM_RC_HASH
+
+non-duplicable storage key represented by objectPublic and its
+parent referenced by parentHandle have different name algorithm
+
+TPM_RC_INSUFFICIENT
+
+inSymSeed is nonempty and failed to retrieve ECC point from the
+secret; or unmarshaling sensitive value from duplicate failed the
+result of inSymSeed decryption
+
+TPM_RC_INTEGRITY
+
+duplicate integrity is broken
+
+TPM_RC_KDF
+
+objectPublic representing decrypting keyed hash object specifies
+invalid KDF
+
+TPM_RC_KEY
+
+inconsistent parameters of objectPublic; or inSymSeed is nonempty
+and parentHandle does not reference a key of supported type; or
+invalid key size in objectPublic representing an asymmetric key
+
+TPM_RC_NO_RESULT
+
+inSymSeed is nonempty and multiplication resulted in ECC point at
+infinity
+
+TPM_RC_OBJECT_MEMORY
+
+no available object slot
+
+TPM_RC_SCHEME
+
+inconsistent attributes decrypt, sign, restricted and key's scheme ID
+in objectPublic; or hash algorithm is inconsistent with the scheme ID
+for keyed hash object
+
+TPM_RC_SIZE
+
+authPolicy size does not match digest size of the name algorithm in
+objectPublic; or symmetricAlg and encryptionKey have different
+sizes; or inSymSeed is nonempty and it is not of the same size as
+RSA key referenced by parentHandle; or unmarshaling sensitive
+value from duplicate failed
+
+TPM_RC_SYMMETRIC
+
+objectPublic is either a storage key with no symmetric algorithm or a
+non-storage key with symmetric algorithm different from
+TPM_ALG_NULL
+
+TPM_RC_TYPE
+
+unsupported type of objectPublic; or non-duplicable storage key
+represented by objectPublic and its parent referenced by
+parentHandle are of different types; or parentHandle is not a storage
+key; or only the public portion of parentHandle is loaded; or
+objectPublic and duplicate are of different types
+
+TPM_RC_VALUE
+
+nonempty inSymSeed and its numeric value is greater than the
+modulus of the key referenced by parentHandle or inSymSeed is
+larger than the size of the digest produced by the name algorithm of
+the symmetric key referenced by parentHandle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 89
+October 31, 2013
+
+ Part 3: Commands
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+
+Trusted Platform Module Library
+
+TPM_RC
+TPM2_Import(
+Import_In
+Import_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+OBJECT
+TPM2B_DATA
+TPMT_SENSITIVE
+TPM2B_NAME
+
+result = TPM_RC_SUCCESS;
+*parentObject;
+data;
+// symmetric key
+sensitive;
+name;
+
+UINT16
+
+innerKeySize = 0;
+
+// encrypt key size for inner
+// wrapper
+
+// Input Validation
+// FixedTPM and fixedParent must be CLEAR
+if(
+in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET
+|| in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET)
+return TPM_RC_ATTRIBUTES + RC_Import_objectPublic;
+// Get parent pointer
+parentObject = ObjectGet(in->parentHandle);
+if(!AreAttributesForParent(parentObject))
+return TPM_RC_TYPE + RC_Import_parentHandle;
+if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
+{
+// Get inner wrap key size
+innerKeySize = in->symmetricAlg.keyBits.sym;
+// Input symmetric key must match the size of algorithm.
+if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
+return TPM_RC_SIZE + RC_Import_encryptionKey;
+}
+else
+{
+// If input symmetric algorithm is NULL, input symmetric key size must
+// be 0 as well
+if(in->encryptionKey.t.size != 0)
+return TPM_RC_SIZE + RC_Import_encryptionKey;
+}
+// See if there is an outer wrapper
+if(in->inSymSeed.t.size != 0)
+{
+// Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
+// TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
+// TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
+result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE",
+&in->inSymSeed, &data);
+pAssert(result != TPM_RC_BINDING);
+if(result != TPM_RC_SUCCESS)
+return TPM_RC_VALUE + RC_Import_inSymSeed;
+}
+else
+{
+data.t.size = 0;
+}
+// Compute name of object
+ObjectComputeName(&(in->objectPublic.t.publicArea), &name);
+
+Page 90
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+
+Part 3: Commands
+
+// Retrieve sensitive from private.
+// TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
+result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle,
+in->objectPublic.t.publicArea.nameAlg,
+(TPM2B_SEED *) &data, &in->symmetricAlg,
+&in->encryptionKey, &sensitive);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Import_duplicate);
+// If the parent of this object has fixedTPM SET, then fully validate this
+// object so that validation can be skipped when it is loaded
+if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
+{
+TPM_HANDLE
+objectHandle;
+// Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
+// TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
+// TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
+// at this point
+result = PublicAttributesValidation(TRUE, in->parentHandle,
+&in->objectPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Import_objectPublic);
+// Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or
+// TPM_RC_OBJECT_MEMORY error may be returned at this point
+result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea,
+&sensitive, NULL, in->parentHandle, FALSE,
+&objectHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Don't need the object, just needed the checks to be performed so
+// flush the object
+ObjectFlush(objectHandle);
+}
+// Command output
+// Prepare output private data from sensitive
+SensitiveToPrivate(&sensitive, &name, in->parentHandle,
+in->objectPublic.t.publicArea.nameAlg,
+&out->outPrivate);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 91
+October 31, 2013
+
+ Part 3: Commands
+
+16
+
+Trusted Platform Module Library
+
+Asymmetric Primitives
+
+16.1
+
+Introduction
+
+The commands in this clause provide low-level primitives for access to the asymmetric algorithms
+implemented in the TPM. Many of these commands are only allowed if the asymmetric key is an
+unrestricted key.
+16.2
+
+TPM2_RSA_Encrypt
+
+16.2.1 General Description
+This command performs RSA encryption using the indicated padding scheme according to PKCS#1v2.1
+(PKCS#1). If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use inScheme to specify
+the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, then inScheme shall either be
+TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME).
+The key referenced by keyHandle is required to be an RSA key (TPM_RC_KEY) with the decrypt attribute
+SET (TPM_RC_ATTRIBUTES).
+NOTE
+
+Requiring that the decrypt attribute be set allows the TPM to ensure that the scheme selection is
+done with the presumption that the scheme of the key is a decryption scheme selection. It is
+understood that this command will operate on a key with only the publi c part loaded so the caller
+may modify any key in any desired way. So, this constraint only serves to simplify the TPM logic.
+
+The three types of allowed padding are:
+1) TPM_ALG_OAEP – Data is OAEP padded as described in 7.1 of PKCS#1 v2.1. The only
+supported mask generation is MGF1.
+2) TPM_ALG_RSAES – Data is padded as described in 7.2 of PKCS#1 v2.1.
+3) TPM_ALG_NULL – Data is not padded by the TPM and the TPM will treat message as an
+unsigned integer and perform a modular exponentiation of message using the public
+exponent of the key referenced by keyHandle. This scheme is only used if both the scheme
+in the key referenced by keyHandle is TPM_ALG_NULL, and the inScheme parameter of the
+command is TPM_ALG_NULL. The input value cannot be larger than the public modulus of
+the key referenced by keyHandle.
+Table 41 — Padding Scheme Selection
+keyHandle→scheme
+
+OAEP
+RSAES
+
+TPM_ALG_RSAES
+
+RSAES
+error (TPM_RC_SCHEME)
+
+TPM_ALG_NULL
+
+OAEP
+
+TPM_ALG_RSAES
+
+error (TPM_RC_SCHEME)
+
+TPM_AGL_OAEP
+
+October 31, 2013
+
+RSAES
+
+TPM_ALG_OAEP
+
+Page 92
+
+TPM_ALG_RSAES
+
+TPM_ALG_NULL
+
+TPM_ALG_OAEP
+
+none
+
+TPM_ALG_OAEP
+
+TPM_ALG_RSAES
+
+padding scheme used
+
+TPM_ALG_NULL
+TPM_ALG_NULL
+
+inScheme
+
+OAEP
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+After padding, the data is RSAEP encrypted according to 5.1.1 of PKCS#1v2.1.
+NOTE 1
+
+It is required that decrypt be SET so that the commands that load a key can validate that the
+scheme is consistent rather than have that deferred until the key is used.
+
+NOTE 2
+
+If it is desired to use a key that had restricted SET, the caller may CLEAR restricted and load the
+public part of the key and use that unrestricted version of the key for encryption.
+
+If inScheme is used, and the scheme requires a hash algorithm it may not be TPM_ALG_NULL.
+NOTE 3
+
+Because only the public portion of the key needs to be loaded for this command, the caller can
+manipulate the attributes of the key in any way desired. As a result , the TPM shall not check the
+consistency of the attributes. The only property checking is that the key is an RSA key and that the
+padding scheme is supported.
+
+The message parameter is limited in size by the padding scheme according to the following table:
+Table 42 — Message Size Limits Based on Padding
+Scheme
+
+Maximum Message Length
+(mLen) in Octets
+
+TPM_ALG_OAEP
+
+mLen  k – 2hLen – 2
+
+TPM_ALG_RSAES
+
+mLen  k – 11
+
+TPM_ALG_NULL
+
+mLen  k
+
+Comments
+
+The numeric value of the message must be
+less than the numeric value of the public
+modulus (n).
+
+NOTES
+1)
+2)
+
+k ≔ the number of byes in the public modulus
+hLen ≔ the number of octets in the digest produced by the hash algorithm used in the process
+
+The label parameter is optional. If provided (label.size != 0) then the TPM shall return TPM_RC_VALUE if
+the last octet in label is not zero. If a zero octet occurs before label.buffer[label.size-1], the TPM shall
+truncate the label at that point. The terminating octet of zero is included in the label used in the padding
+scheme.
+NOTE 4
+
+If the scheme does not use a label, the TPM will still verify that label is properly formatted if label is
+present.
+
+The function returns padded and encrypted value outData.
+The message parameter in the command may be encrypted using parameter encryption.
+NOTE 5
+
+Only the public area of keyHandle is required to be loaded. A public key may be loaded with any
+desired scheme. If the scheme is to be changed, a different public area must be loaded.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 93
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.2.2 Command and Response
+Table 43 — TPM2_RSA_Encrypt Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_RSA_Encrypt
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+reference to public portion of RSA key to use for
+encryption
+Auth Index: None
+message to be encrypted
+
+TPM2B_PUBLIC_KEY_RSA
+
+message
+
+TPMT_RSA_DECRYPT+
+
+inScheme
+
+TPM2B_DATA
+
+label
+
+NOTE 1
+
+The data type was chosen because it limits the
+overall size of the input to no greater than the size
+of the largest RSA public key. This may be larger
+than allowed for keyHandle.
+
+the padding scheme to use if scheme associated with
+keyHandle is TPM_ALG_NULL
+optional label L to be associated with the message
+Size of the buffer is zero if no label is present
+NOTE 2
+
+See description of label above.
+
+Table 44 — TPM2_RSA_Encrypt Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PUBLIC_KEY_RSA
+
+outData
+
+Page 94
+October 31, 2013
+
+encrypted output
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "RSA_Encrypt_fp.h"
+#ifdef TPM_ALG_RSA
+Error Returns
+TPM_RC_ATTRIBUTES
+
+decrypt attribute is not SET in key referenced by keyHandle
+
+TPM_RC_KEY
+
+keyHandle does not reference an RSA key
+
+TPM_RC_SCHEME
+
+incorrect input scheme, or the chosen scheme is not a valid RSA
+decrypt scheme
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+the numeric value of message is greater than the public modulus of
+the key referenced by keyHandle, or label is not a null-terminated
+string
+
+TPM_RC
+TPM2_RSA_Encrypt(
+RSA_Encrypt_In
+RSA_Encrypt_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+TPMT_RSA_DECRYPT
+char
+
+result;
+*rsaKey;
+*scheme;
+*label = NULL;
+
+)
+{
+
+// Input Validation
+rsaKey = ObjectGet(in->keyHandle);
+// selected key must be an RSA key
+if(rsaKey->publicArea.type != TPM_ALG_RSA)
+return TPM_RC_KEY + RC_RSA_Encrypt_keyHandle;
+// selected key must have the decryption attribute
+if(rsaKey->publicArea.objectAttributes.decrypt != SET)
+return TPM_RC_ATTRIBUTES + RC_RSA_Encrypt_keyHandle;
+// Is there a label?
+if(in->label.t.size > 0)
+{
+// label is present, so make sure that is it NULL-terminated
+if(in->label.t.buffer[in->label.t.size - 1] != 0)
+return TPM_RC_VALUE + RC_RSA_Encrypt_label;
+label = (char *)in->label.t.buffer;
+}
+// Command Output
+// Select a scheme for encryption
+scheme = CryptSelectRSAScheme(in->keyHandle, &in->inScheme);
+if(scheme == NULL)
+return TPM_RC_SCHEME + RC_RSA_Encrypt_inScheme;
+// Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy
+// CryptEncyptRSA. Note: It can also return TPM_RC_ATTRIBUTES if the key does
+// not have the decrypt attribute but that was checked above.
+out->outData.t.size = sizeof(out->outData.t.buffer);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 95
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+
+Trusted Platform Module Library
+
+result = CryptEncryptRSA(&out->outData.t.size, out->outData.t.buffer, rsaKey,
+scheme, in->message.t.size, in->message.t.buffer,
+label);
+return result;
+}
+#endif
+
+Page 96
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.3
+
+Part 3: Commands
+
+TPM2_RSA_Decrypt
+
+16.3.1 General Description
+This command performs RSA decryption using the indicated padding scheme according to PKCS#1v2.1
+(PKCS#1).
+The scheme selection for this command is the same as for TPM2_RSA_Encrypt() and is shown in Table
+41.
+The key referenced by keyHandle shall be an RSA key (TPM_RC_KEY) with restricted CLEAR and
+decrypt SET (TPM_RC_ATTRIBUTES).
+This command uses the private key of keyHandle for this operation and authorization is required.
+The TPM will perform a modular exponentiation of ciphertext using the private exponent associated with
+keyHandle (this is described in PKCS#1v2.1, clause 5.1.2). It will then validate the padding according to
+the selected scheme. If the padding checks fail, TPM_RC_VALUE is returned. Otherwise, the data is
+returned with the padding removed. If no padding is used, the returned value is an unsigned integer value
+that is the result of the modular exponentiation of cipherText using the private exponent of keyHandle.
+The returned value may include leading octets zeros so that it is the same size as the public modulus. For
+the other padding schemes, the returned value will be smaller than the public modulus but will contain all
+the data remaining after padding is removed and this may include leading zeros if the original encrypted
+value contained leading zeros..
+If a label is used in the padding process of the scheme, the label parameter is required to be present in
+the decryption process and label is required to be the same in both cases. The TPM shall verify that the
+label is consistent and if not it shall return TPM_RC_VALUE.
+If label is present (label.size != 0), it
+shall be a NULL-terminated string or the TPM will return TPM_RC_VALUE.
+NOTE 1
+
+The size of label includes the terminating null.
+
+The message parameter in the response may be encrypted using parameter encryption.
+If the decryption scheme does not require a hash function, the hash parameter of inScheme may be set
+to any valid hash function or TPM_ALG_NULL.
+If the description scheme does not require a label, the value in label is not used but the size of the label
+field is checked for consistency with the indicated data type (TPM2B_DATA). That is, the field may not be
+larger than allowed for a TPM2B_DATA.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 97
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.3.2 Command and Response
+Table 45 — TPM2_RSA_Decrypt Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_RSA_Decrypt
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+RSA key to use for decryption
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_PUBLIC_KEY_RSA
+
+cipherText
+
+NOTE
+
+TPMT_RSA_DECRYPT+
+
+inScheme
+
+the padding scheme to use if scheme associated with
+keyHandle is TPM_ALG_NULL
+
+TPM2B_DATA
+
+label
+
+label whose association with the message is to be
+verified
+
+cipher text to be decrypted
+An encrypted RSA data block is the size of the
+public modulus.
+
+Table 46 — TPM2_RSA_Decrypt Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PUBLIC_KEY_RSA
+
+message
+
+Page 98
+October 31, 2013
+
+decrypted output
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "RSA_Decrypt_fp.h"
+#ifdef TPM_ALG_RSA
+Error Returns
+TPM_RC_KEY
+
+keyHandle does not reference an unrestricted decrypt key
+
+TPM_RC_SCHEME
+
+incorrect input scheme, or the chosen scheme is not a valid RSA
+decrypt scheme
+
+TPM_RC_SIZE
+
+cipherText is not the size of the modulus of key referenced by
+keyHandle
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+label is not a null terminated string or the value of cipherText is
+greater that the modulus of keyHandle
+
+TPM_RC
+TPM2_RSA_Decrypt(
+RSA_Decrypt_In
+RSA_Decrypt_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+TPMT_RSA_DECRYPT
+char
+
+result;
+*rsaKey;
+*scheme;
+*label = NULL;
+
+)
+{
+
+// Input Validation
+rsaKey = ObjectGet(in->keyHandle);
+// The selected key must be an RSA key
+if(rsaKey->publicArea.type != TPM_ALG_RSA)
+return TPM_RC_KEY + RC_RSA_Decrypt_keyHandle;
+// The selected key must be an unrestricted decryption key
+if(
+rsaKey->publicArea.objectAttributes.restricted == SET
+|| rsaKey->publicArea.objectAttributes.decrypt == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_RSA_Decrypt_keyHandle;
+//
+//
+//
+//
+
+NOTE: Proper operation of this command requires that the sensitive area
+of the key is loaded. This is assured because authorization is required
+to use the sensitive area of the key. In order to check the authorization,
+the sensitive area has to be loaded, even if authorization is with policy.
+
+// If label is present, make sure that it is a NULL-terminated string
+if(in->label.t.size > 0)
+{
+// Present, so make sure that it is NULL-terminated
+if(in->label.t.buffer[in->label.t.size - 1] != 0)
+return TPM_RC_VALUE + RC_RSA_Decrypt_label;
+label = (char *)in->label.t.buffer;
+}
+// Command Output
+// Select a scheme for decrypt.
+scheme = CryptSelectRSAScheme(in->keyHandle, &in->inScheme);
+if(scheme == NULL)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 99
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+Trusted Platform Module Library
+
+return TPM_RC_SCHEME + RC_RSA_Decrypt_inScheme;
+// Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be
+// returned by CryptDecryptRSA.
+// NOTE: CryptDecryptRSA can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING
+// when the key is not a decryption key but that was checked above.
+out->message.t.size = sizeof(out->message.t.buffer);
+result = CryptDecryptRSA(&out->message.t.size, out->message.t.buffer, rsaKey,
+scheme, in->cipherText.t.size,
+in->cipherText.t.buffer,
+label);
+return result;
+}
+#endif
+
+Page 100
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.4
+
+Part 3: Commands
+
+TPM2_ECDH_KeyGen
+
+16.4.1 General Description
+This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe ≔ [de]G). It uses the private
+ephemeral key and a loaded public key (QS) to compute the shared secret value (P ≔ [hde]QS).
+
+keyHandle shall refer to a loaded ECC key. The sensitive portion of this key need not be loaded.
+The curve parameters of the loaded ECC key are used to generate the ephemeral key.
+NOTE 1
+
+This function is the equivalent of encrypting data to another object’s public key. The seed value is
+used in a KDF to generate a symmetric key and that key is used to encrypt the data. Once the data
+is encrypted and the symmetric key discarded, only the ob ject with the private portion of the
+keyHandle will be able to decrypt it.
+
+The zPoint in the response may be encrypted using parameter encryption.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 101
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.4.2 Command and Response
+Table 47 — TPM2_ECDH_KeyGen Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ECDH_KeyGen
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+Handle of a loaded ECC key public area.
+Auth Index: None
+
+Table 48 — TPM2_ECDH_KeyGen Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+zPoint
+
+results of P ≔ h[de]Qs
+
+TPM2B_ECC_POINT
+
+pubPoint
+
+generated ephemeral public point (Qe)
+
+Page 102
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.4.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ECDH_KeyGen_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_KEY
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+keyHandle does not reference a non-restricted decryption ECC key
+
+TPM_RC
+TPM2_ECDH_KeyGen(
+ECDH_KeyGen_In
+ECDH_KeyGen_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+TPM2B_ECC_PARAMETER
+TPM_RC
+
+*eccKey;
+sensitive;
+result;
+
+// Input Validation
+eccKey = ObjectGet(in->keyHandle);
+// Input key must be a non-restricted, decrypt ECC key
+if(
+eccKey->publicArea.type != TPM_ALG_ECC
+|| eccKey->publicArea.objectAttributes.restricted == SET
+|| eccKey->publicArea.objectAttributes.decrypt != SET
+)
+return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
+// Command Output
+do
+{
+// Create ephemeral ECC key
+CryptNewEccKey(eccKey->publicArea.parameters.eccDetail.curveID,
+&out->pubPoint.t.point, &sensitive);
+out->pubPoint.t.size = TPMS_ECC_POINT_Marshal(&out->pubPoint.t.point,
+NULL, NULL);
+// Compute Z
+result = CryptEccPointMultiply(&out->zPoint.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+&sensitive, &eccKey->publicArea.unique.ecc);
+// The point in the key is not on the curve. Indicate that the key is bad.
+if(result == TPM_RC_ECC_POINT)
+return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
+// The other possible error is TPM_RC_NO_RESULT indicating that the
+// multiplication resulted in the point at infinity, so get a new
+// random key and start over (hardly ever happens).
+}
+while(result != TPM_RC_SUCCESS);
+// Marshal the values to generate the point.
+out->zPoint.t.size = TPMS_ECC_POINT_Marshal(&out->zPoint.t.point, NULL, NULL);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 103
+October 31, 2013
+
+ Part 3: Commands
+
+16.5
+
+Trusted Platform Module Library
+
+TPM2_ECDH_ZGen
+
+16.5.1 General Description
+This command uses the TPM to recover the Z value from a public point (QB) and a private key (ds). It will
+perform the multiplication of the provided inPoint (QB) with the private key (ds) and return the coordinates
+of the resultant point (Z = (xZ , yZ) ≔ [hds]QB; where h is the cofactor of the curve).
+keyHandle shall refer to a loaded, ECC key (TPM_RC_KEY) with the restricted attribute CLEAR and the
+decrypt attribute SET (TPM_RC_ATTRIBUTES).
+The scheme of the key referenced by keyHandle is required to be either TPM_ALG_ECDH or
+TPM_ALG_NULL (TPM_RC_SCHEME).
+inPoint is required to be on the curve of the key referenced by keyHandle (TPM_RC_ECC_POINT).
+The parameters of the key referenced by keyHandle are used to perform the point multiplication.
+
+Page 104
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.5.2 Command and Response
+Table 49 — TPM2_ECDH_ZGen Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ECDH_ZGen
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+handle of a loaded ECC key
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_ECC_POINT
+
+inPoint
+
+a public key
+
+Table 50 — TPM2_ECDH_ZGen Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+outPoint
+
+Family “2.0”
+Level 00 Revision 00.99
+
+X and Y coordinates of the product of the multiplication
+
+Z = (xZ , yZ) ≔ [hdS]QB
+
+Published
+Copyright © TCG 2006-2013
+
+Page 105
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ECDH_ZGen_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_KEY
+
+keyHandle does not reference a non-restricted decryption ECC key
+
+TPM_RC_ECC_POINT
+
+invalid argument
+
+TPM_RC_NO_RESULT
+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
+33
+34
+35
+36
+37
+38
+39
+
+Meaning
+
+multiplying inPoint resulted in a point at infinity
+
+TPM_RC
+TPM2_ECDH_ZGen(
+ECDH_ZGen_In
+ECDH_ZGen_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+OBJECT
+
+result;
+*eccKey;
+
+// Input Validation
+eccKey = ObjectGet(in->keyHandle);
+// Input key must be a non-restricted, decrypt ECC key
+if(
+eccKey->publicArea.type != TPM_ALG_ECC
+|| eccKey->publicArea.objectAttributes.restricted == SET
+|| eccKey->publicArea.objectAttributes.decrypt != SET
+)
+return TPM_RC_KEY + RC_ECDH_ZGen_keyHandle;
+// Command Output
+// Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here.
+result = CryptEccPointMultiply(&out->outPoint.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+&eccKey->sensitive.sensitive.ecc,
+&in->inPoint.t.point);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint);
+out->outPoint.t.size = TPMS_ECC_POINT_Marshal(&out->outPoint.t.point,
+NULL, NULL);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 106
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.6
+
+Part 3: Commands
+
+TPM2_ECC_Parameters
+
+16.6.1 General Description
+This command returns the parameters of an ECC curve identified by its TCG-assigned curveID.
+16.6.2 Command and Response
+Table 51 — TPM2_ECC_Parameters Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ECC_Parameters
+
+TPMI_ECC_CURVE
+
+curveID
+
+parameter set selector
+
+Table 52 — TPM2_ECC_Parameters Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMS_ALGORITHM_DETAIL_ECC
+
+parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ECC parameters for the selected curve
+
+Published
+Copyright © TCG 2006-2013
+
+Page 107
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ECC_Parameters_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_VALUE
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
+Meaning
+Unsupported ECC curve ID
+
+TPM_RC
+TPM2_ECC_Parameters(
+ECC_Parameters_In
+ECC_Parameters_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Get ECC curve parameters
+if(CryptEccGetParameters(in->curveID, &out->parameters))
+return TPM_RC_SUCCESS;
+else
+return TPM_RC_VALUE + RC_ECC_Parameters_curveID;
+}
+#endif
+
+16.7
+16.7.1
+
+TPM2_ZGen_2Phase
+General Description
+
+This command supports two-phase key exchange protocols. The command is used in combination with
+TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key and returns the public
+point of that ephemeral key along with a numeric value that allows the TPM to regenerate the associated
+private key.
+The input parameters for this command are a static public key (inQsU), an ephemeral key (inQeU) from
+party B, and the commitCounter returned by TPM2_EC_Ephemeral(). The TPM uses the counter value to
+regenerate the ephemeral private key (de,V) and the associated public key (Qe,V). keyA provides the static
+ephemeral elements ds,V and Qs,V. This provides the two pairs of ephemeral and static keys that are
+required for the schemes supported by this command.
+The TPM will compute Z or Zs and Ze according to the selected scheme. If the scheme is not a two-phase
+key exchange scheme or if the scheme is not supported, the TPM will return TPM_RC_SCHEME.
+It is an error if inQsB or inQeB are not on the curve of keyA (TPM_RC_ECC_POINT).
+The two-phase key schemes that were assigned an algorithm ID as of the time of the publication of this
+specification are TPM_ALG_ECDH, TPM_ALG_ECMQV, and TPM_ALG_SM2.
+If this command is supported, then support for TPM_ALG_ECDH is required. Support for
+TPM_ALG_ECMQV or TPM_ALG_SM2 is optional.
+NOTE 1
+
+If SM2 is supported and this command is supported, then the implementation is required to support
+the key exchange protocol of SM2, part 3.
+
+For TPM_ALG_ECDH outZ1 will be Zs and outZ2 will Ze as defined in 6.1.1.2 of SP800-56A.
+
+Page 108
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+NOTE 2
+
+Part 3: Commands
+
+A non-restricted decryption key using ECDH may be used in either TPM2_ECDH_ZGen() or
+TPM2_ZGen_2Phase as the computation done with the private part of keyA is the same in both
+cases.
+
+For TPM_ALG_ECMQV or TPM_ALG_SM2 outZ1 will be Z and outZ2 will be an Empty Point.
+NOTE 3
+
+An Empty Point has two Empty Buffers as coordinates meaning the minimum size value for outZ2
+will be four.
+
+If the input scheme is TPM_ALG_ECDH, then outZ1 will be Zs and outZ2 will be Ze. For schemes like
+MQV (including SM2), outZ1 will contain the computed value and outZ2 will be an Empty Point.
+NOTE
+
+The Z values returned by the TPM are a full point and not ju st an x-coordinate.
+
+If a computation of either Z produces the point at infinity, then the corresponding Z value will be an Empty
+Point.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 109
+October 31, 2013
+
+ Part 3: Commands
+
+16.7.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 53 — TPM2_ZGen_2Phase Command
+
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+Description
+
+TPM_CC_ ZGen_2Phase
+handle of an unrestricted decryption key ECC
+The private key referenced by this handle is used as dS,A
+
+TPMI_DH_OBJECT
+
+@keyA
+
+TPM2B_ECC_POINT
+
+inQsB
+
+other party’s static public key (Qs,B = (Xs,B, Ys,B))
+
+TPM2B_ECC_POINT
+
+inQeB
+
+other party's ephemeral public key (Qe,B = (Xe,B, Ye,B))
+
+TPMI_ECC_KEY_EXCHANGE
+
+inScheme
+
+the key exchange scheme
+
+UINT16
+
+counter
+
+value returned by TPM2_EC_Ephemeral()
+
+Auth Index: 1
+Auth Role: USER
+
+Table 54 — TPM2_ZGen_2Phase Response
+Type
+
+Name
+
+TPM_ST
+
+tag
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+outZ1
+
+X and Y coordinates of the computed value (scheme
+dependent)
+
+TPM2B_ECC_POINT
+
+outZ2
+
+X and Y coordinates of the second computed value
+(scheme dependent)
+
+Page 110
+October 31, 2013
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.7.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "ZGen_2Phase_fp.h"
+#if defined TPM_ALG_ECC && (CC_ZGen_2Phase == YES)
+
+This command uses the TPM to recover one or two Z values in a two phase key exchange protocol
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by keyA is restricted or not a decrypt key
+
+TPM_RC_ECC_POINT
+
+inQsB or inQeB is not on the curve of the key reference by keyA
+
+TPM_RC_KEY
+
+key referenced by keyA is not an ECC key
+
+TPM_RC_SCHEME
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
+Meaning
+
+the scheme of the key referenced by keyA is not TPM_ALG_NULL,
+TPM_ALG_ECDH, TPM_ALG_ECMQV or TPM_ALG_SM2
+
+TPM_RC
+TPM2_ZGen_2Phase(
+ZGen_2Phase_In
+ZGen_2Phase_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+OBJECT
+TPM2B_ECC_PARAMETER
+TPM_ALG_ID
+
+result;
+*eccKey;
+r;
+scheme;
+
+// Input Validation
+eccKey = ObjectGet(in->keyA);
+// keyA must be an ECC key
+if(eccKey->publicArea.type != TPM_ALG_ECC)
+return TPM_RC_KEY + RC_ZGen_2Phase_keyA;
+// keyA must not be restricted and must be a decrypt key
+if(
+eccKey->publicArea.objectAttributes.restricted == SET
+|| eccKey->publicArea.objectAttributes.decrypt != SET
+)
+return TPM_RC_ATTRIBUTES + RC_ZGen_2Phase_keyA;
+// if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise
+// the input scheme must be the same as the scheme of keyA
+scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme;
+if(scheme != TPM_ALG_NULL)
+{
+if(scheme != in->inScheme)
+return TPM_RC_SCHEME + RC_ZGen_2Phase_inScheme;
+}
+else
+scheme = in->inScheme;
+if(scheme == TPM_ALG_NULL)
+return TPM_RC_SCHEME + RC_ZGen_2Phase_inScheme;
+// Input points must be on the curve of keyA
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+&in->inQsB.t.point))
+return TPM_RC_ECC_POINT + RC_ZGen_2Phase_inQsB;
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 111
+October 31, 2013
+
+ Part 3: Commands
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
+Trusted Platform Module Library
+
+&in->inQeB.t.point))
+return TPM_RC_ECC_POINT + RC_ZGen_2Phase_inQeB;
+if(!CryptGenerateR(&r, &in->counter,
+eccKey->publicArea.parameters.eccDetail.curveID,
+NULL))
+return TPM_RC_VALUE + RC_ZGen_2Phase_counter;
+// Command Output
+result = CryptEcc2PhaseKeyExchange(&out->outZ1.t.point,
+&out->outZ2.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+scheme,
+&eccKey->sensitive.sensitive.ecc,
+&r,
+&in->inQsB.t.point,
+&in->inQeB.t.point);
+if(result != TPM_RC_SUCCESS)
+return result;
+CryptEndCommit(in->counter);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 112
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+17
+17.1
+
+Part 3: Commands
+
+Symmetric Primitives
+Introduction
+
+The commands in this clause provide low-level primitives for access to the symmetric algorithms
+implemented in the TPM that operate on blocks of data. These include symmetric encryption and
+decryption as well as hash and HMAC. All of the commands in this group are stateless. That is, they have
+no persistent state that is retained in the TPM when the command is complete.
+For hashing, HMAC, and Events that require large blocks of data with retained state, the sequence
+commands are provided (see clause 1).
+Some of the symmetric encryption/decryption modes use an IV. When an IV is used, it may be an
+initiation value or a chained value from a previous stage. The chaining for each mode is:
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 113
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+Table 55 — Symmetric Chaining Process
+
+Mode
+
+Chaining process
+
+TPM_ALG_CTR
+
+The TPM will increment the entire IV provided by the caller. The last encrypted value will be
+returned to the caller as ivOut. This can be the input value to the next encrypted buffer.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+EXAMPLE 1 AES requires that ivIn be 128 bits (16 octets).
+
+ivOut will be the size of a cipher block and not the size of the last encrypted block.
+NOTE
+
+ivOut will be the value of the counter after the last block is encrypted.
+
+EXAMPLE 2 If ivIn were 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0016 and four data blocks
+were encrypted, ivOut will have a value of
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0416.
+
+All the bits of the IV are incremented as if it were an unsigned integer.
+TPM_ALG_OFB
+
+In Output Feedback (OFB), the output of the pseudo-random function (the block encryption
+algorithm) is XORed with a plaintext block to produce a ciphertext block. ivOut will be the
+value that was XORed with the last plaintext block. That value can be used as the ivIn for a
+next buffer.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+ivOut will be the size of a cipher block and not the size of the last encrypted block.
+
+TPM_ALG_CBC
+
+For Cipher Block Chaining (CBC), a block of ciphertext is XORed with the next plaintext
+block and that block is encrypted. The encrypted block is then input to the encryption of the
+next block. The last ciphertext block then is used as an IV for the next buffer.
+Even though the last ciphertext block is evident in the encrypted data, it is also returned in
+ivOut.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+inData is required to be an even multiple of the block encrypted by the selected algorithm
+and key combination. If the size of inData is not correct, the TPM shall return
+TPM_RC_SIZE.
+
+TPM_ALG_CFB
+
+Similar to CBC in that the last ciphertext block is an input to the encryption of the next block.
+ivOut will be the value that was XORed with the last plaintext block. That value can be used
+as the ivIn for a next buffer.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+ivOut will be the size of a cipher block and not the size of the last encrypted block.
+
+TPM_ALG_ECB
+
+Electronic Codebook (ECB) has no chaining. Each block of plaintext is encrypted using the
+key. ECB does not support chaining and ivIn shall be the Empty Buffer. ivOut will be the
+Empty Buffer.
+inData is required to be an even multiple of the block encrypted by the selected algorithm
+and key combination. If the size of inData is not correct, the TPM shall return
+TPM_RC_SIZE.
+
+Page 114
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+17.2
+
+Part 3: Commands
+
+TPM2_EncryptDecrypt
+
+17.2.1 General Description
+This command performs symmetric encryption or decryption.
+keyHandle shall reference a symmetric cipher object (TPM_RC_KEY).
+For a restricted key, mode shall be either the same as the mode of the key, or TPM_ALG_NULL
+(TPM_RC_VALUE). For an unrestricted key, mode may be the same or different from the mode of the key
+but both shall not be TPM_ALG_NULL (TPM_RC_VALUE).
+If the TPM allows this command to be canceled before completion, then the TPM may produce
+incremental results and return TPM_RC_SUCCESS rather than TPM_RC_CANCEL. In such case,
+outData may be less than inData.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 115
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+17.2.2 Command and Response
+Table 56 — TPM2_EncryptDecrypt Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EncryptDecrypt
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+the symmetric key used for the operation
+Auth Index: 1
+Auth Role: USER
+
+TPMI_YES_NO
+
+decrypt
+
+if YES, then the operation is decryption; if NO, the
+operation is encryption
+
+TPMI_ALG_SYM_MODE+
+
+mode
+
+symmetric mode
+For a restricted key, this field shall match the default
+mode of the key or be TPM_ALG_NULL.
+
+TPM2B_IV
+
+ivIn
+
+an initial value as required by the algorithm
+
+TPM2B_MAX_BUFFER
+
+inData
+
+the data to be encrypted/decrypted
+
+Table 57 — TPM2_EncryptDecrypt Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_BUFFER
+
+outData
+
+encrypted output
+
+TPM2B_IV
+
+ivOut
+
+chaining value to use for IV in next round
+
+Page 116
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+17.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "EncryptDecrypt_fp.h"
+Error Returns
+TPM_RC_KEY
+
+is not a symmetric decryption key with both public and private
+portions loaded
+
+TPM_RC_SIZE
+
+IvIn size is incompatible with the block cipher mode; or inData size is
+not an even multiple of the block size for CBC or ECB mode
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+
+Meaning
+
+keyHandle is restricted and the argument mode does not match the
+key's mode
+
+TPM_RC
+TPM2_EncryptDecrypt(
+EncryptDecrypt_In
+EncryptDecrypt_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+UINT16
+UINT16
+BYTE
+TPM_ALG_ID
+
+*symKey;
+keySize;
+blockSize;
+*key;
+alg;
+
+// Input Validation
+symKey = ObjectGet(in->keyHandle);
+// The input key should be a symmetric decrypt key.
+if(
+symKey->publicArea.type != TPM_ALG_SYMCIPHER
+|| symKey->attributes.publicOnly == SET)
+return TPM_RC_KEY + RC_EncryptDecrypt_keyHandle;
+// If the input mode is TPM_ALG_NULL, use the key's mode
+if( in->mode == TPM_ALG_NULL)
+in->mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;
+// If the key is restricted, the input sym mode should match the key's sym
+// mode
+if(
+symKey->publicArea.objectAttributes.restricted == SET
+&& symKey->publicArea.parameters.symDetail.sym.mode.sym != in->mode)
+return TPM_RC_VALUE + RC_EncryptDecrypt_mode;
+// If the mode is null, then we have a problem.
+// Note: Construction of a TPMT_SYM_DEF does not allow the 'mode' to be
+// TPM_ALG_NULL so setting in->mode to the mode of the key should have
+// produced a valid mode. However, this is suspenders.
+if(in->mode == TPM_ALG_NULL)
+return TPM_RC_VALUE + RC_EncryptDecrypt_mode;
+// The input iv for ECB mode should be null. All the other modes should
+// have an iv size same as encryption block size
+keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym;
+alg = symKey->publicArea.parameters.symDetail.sym.algorithm;
+blockSize = CryptGetSymmetricBlockSize(alg, keySize);
+if(
+(in->mode == TPM_ALG_ECB && in->ivIn.t.size != 0)
+|| (in->mode != TPM_ALG_ECB && in->ivIn.t.size != blockSize))
+return TPM_RC_SIZE + RC_EncryptDecrypt_ivIn;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 117
+October 31, 2013
+
+ Part 3: Commands
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+
+Trusted Platform Module Library
+
+// The input data size of CBC mode or ECB mode must be an even multiple of
+// the symmetric algorithm's block size
+if(
+(in->mode == TPM_ALG_CBC || in->mode == TPM_ALG_ECB)
+&& (in->inData.t.size % blockSize) != 0)
+return TPM_RC_SIZE + RC_EncryptDecrypt_inData;
+// Copy IV
+// Note: This is copied here so that the calls to the encrypt/decrypt functions
+// will modify the output buffer, not the input buffer
+out->ivOut = in->ivIn;
+// Command Output
+key = symKey->sensitive.sensitive.sym.t.buffer;
+// For symmetric encryption, the cipher data size is the same as plain data
+// size.
+out->outData.t.size = in->inData.t.size;
+if(in->decrypt == YES)
+{
+// Decrypt data to output
+CryptSymmetricDecrypt(out->outData.t.buffer,
+alg,
+keySize, in->mode, key,
+&(out->ivOut),
+in->inData.t.size,
+in->inData.t.buffer);
+}
+else
+{
+// Encrypt data to output
+CryptSymmetricEncrypt(out->outData.t.buffer,
+alg,
+keySize,
+in->mode, key,
+&(out->ivOut),
+in->inData.t.size,
+in->inData.t.buffer);
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 118
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+17.3
+
+Part 3: Commands
+
+TPM2_Hash
+
+17.3.1 General Description
+This command performs a hash operation on a data buffer and returns the results.
+NOTE
+
+If the data buffer to be hashed is larger than will fit into the TPM’s input buffer, then the sequence
+hash commands will need to be used.
+
+If the results of the hash will be used in a signing operation that uses a restricted signing key, then the
+ticket returned by this command can indicate that the hash is safe to sign.
+If the digest is not safe to sign, then the TPM will return a TPMT_TK_HASHCHECK with the hierarchy set
+to TPM_RH_NULL and digest set to the Empty Buffer.
+If hierarchy is TPM_RH_NULL, then digest in the ticket will be the Empty Buffer.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 119
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+17.3.2 Command and Response
+Table 58 — TPM2_Hash Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+Shall have at least one session
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Hash
+
+TPM2B_MAX_BUFFER
+
+data
+
+data to be hashed
+
+TPMI_ALG_HASH
+
+hashAlg
+
+algorithm for the hash being computed – shall not be
+TPM_ALG_NULL
+
+TPMI_RH_HIERARCHY+
+
+hierarchy
+
+hierarchy to use for the ticket (TPM_RH_NULL allowed)
+
+Table 59 — TPM2_Hash Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+outHash
+
+results
+
+validation
+
+ticket indicating that the sequence of octets used to
+compute outDigest did not start with
+TPM_GENERATED_VALUE
+will be a NULL ticket if the digest may not be signed
+with a restricted key
+
+TPMT_TK_HASHCHECK
+
+Page 120
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+17.3.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+
+#include "InternalRoutines.h"
+#include "Hash_fp.h"
+
+TPM_RC
+TPM2_Hash(
+Hash_In
+Hash_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+HASH_STATE
+
+hashState;
+
+// Command Output
+// Output hash
+// Start hash stack
+out->outHash.t.size = CryptStartHash(in->hashAlg, &hashState);
+// Adding hash data
+CryptUpdateDigest2B(&hashState, &in->data.b);
+// Complete hash
+CryptCompleteHash2B(&hashState, &out->outHash.b);
+// Output ticket
+out->validation.tag = TPM_ST_HASHCHECK;
+out->validation.hierarchy = in->hierarchy;
+if(in->hierarchy == TPM_RH_NULL)
+{
+// Ticket is not required
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else if( in->data.t.size >= sizeof(TPM_GENERATED)
+&& !TicketIsSafe(&in->data.b))
+{
+// Ticket is not safe
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else
+{
+// Compute ticket
+TicketComputeHashCheck(in->hierarchy, &out->outHash, &out->validation);
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 121
+October 31, 2013
+
+ Part 3: Commands
+
+17.4
+
+Trusted Platform Module Library
+
+TPM2_HMAC
+
+17.4.1 General Description
+This command performs an HMAC on the supplied data using the indicated hash algorithm.
+The caller shall provide proper authorization for use of handle.
+If the sign attribute is not SET in the key referenced by handle then the TPM shall return
+TPM_RC_ATTRIBUTES. If the key type is not TPM_ALG_KEYEDHASH then the TPM shall return
+TPM_RC_TYPE.
+If handle references a restricted key, then the hash algorithm specified in the key's scheme is used as the
+hash algorithm for the HMAC and the TPM shall return TPM_RC_VALUE if hashAlg is not
+TPM_ALG_NULL or the same algorithm as selected in the key's scheme.
+NOTE 1
+A restricted key may only have one of sign or decrypt SET and the default scheme may not
+be TPM_ALG_NULL. These restrictions are enforced by TPM2_Create() and TPM2_CreatePrimary(),
+If the key referenced by handle is not restricted, then the TPM will use hashAlg for the HMAC. However, if
+hashAlg is TPM_ALG_NULL the TPM will use the default scheme of the key.
+If both hashAlg and the key default are TPM_ALG_NULL, the TPM shall return TPM_RC_VALUE.
+NOTE
+
+A key may only have both sign and decrypt SET if the key is unrestricted. When bo th sign and
+decrypt are set, there is no default scheme for the key and the hash algorithm must be specified .
+
+Page 122
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+17.4.2 Command and Response
+Table 60 — TPM2_HMAC Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HMAC
+
+TPMI_DH_OBJECT
+
+@handle
+
+handle for the symmetric signing key providing the
+HMAC key
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+HMAC data
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+algorithm to use for HMAC
+
+Table 61 — TPM2_HMAC Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+outHMAC
+
+Family “2.0”
+Level 00 Revision 00.99
+
+the returned HMAC in a sized buffer
+
+Published
+Copyright © TCG 2006-2013
+
+Page 123
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+17.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HMAC_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by handle is not a signing key
+
+TPM_RC_TYPE
+
+key referenced by handle is not an HMAC key
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+hashAlg specified when the key is restricted is neither
+TPM_ALG_NULL not equal to that of the key scheme; or both
+hashAlg and the key scheme's algorithm are TPM_ALG_NULL
+
+TPM_RC
+TPM2_HMAC(
+HMAC_In
+HMAC_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+HMAC_STATE
+OBJECT
+TPMI_ALG_HASH
+TPMT_PUBLIC
+
+hmacState;
+*hmacObject;
+hashAlg;
+*publicArea;
+
+)
+{
+
+// Input Validation
+// Get HMAC key object and public area pointers
+hmacObject = ObjectGet(in->handle);
+publicArea = &hmacObject->publicArea;
+// Make sure that the key is an HMAC signing key
+if(publicArea->type != TPM_ALG_KEYEDHASH)
+return TPM_RC_TYPE + RC_HMAC_handle;
+if(publicArea->objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_HMAC_handle;
+// Assume that the key default scheme is used
+hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
+// if the key is restricted, then need to use the scheme of the key and the
+// input algorithm must be TPM_ALG_NULL or the same as the key scheme
+if(publicArea->objectAttributes.restricted == SET)
+{
+if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
+hashAlg = TPM_ALG_NULL;
+}
+else
+{
+// for a non-restricted key, use hashAlg if it is provided;
+if(in->hashAlg != TPM_ALG_NULL)
+hashAlg = in->hashAlg;
+}
+// if the hashAlg is TPM_ALG_NULL, then the input hashAlg is not compatible
+// with the key scheme or type
+if(hashAlg == TPM_ALG_NULL)
+return TPM_RC_VALUE + RC_HMAC_hashAlg;
+// Command Output
+
+Page 124
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+Part 3: Commands
+
+// Start HMAC stack
+out->outHMAC.t.size = CryptStartHMAC2B(hashAlg,
+&hmacObject->sensitive.sensitive.bits.b,
+&hmacState);
+// Adding HMAC data
+CryptUpdateDigest2B(&hmacState, &in->buffer.b);
+// Complete HMAC
+CryptCompleteHMAC2B(&hmacState, &out->outHMAC.b);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 125
+October 31, 2013
+
+ Part 3: Commands
+
+18
+
+Trusted Platform Module Library
+
+Random Number Generator
+
+18.1
+
+TPM2_GetRandom
+
+18.1.1 General Description
+This command returns the next bytesRequested octets from the random number generator (RNG).
+NOTE 1
+
+It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG
+octets such that the frequency of bytesRequested being more than the number of octets available is
+an infrequent occurrence.
+
+If bytesRequested is more than will fit into a TPM2B_DIGEST on the TPM, no error is returned but the
+TPM will only return as much data as will fit into a TPM2B_DIGEST buffer for the TPM.
+NOTE 2
+
+TPM2B_DIGEST is large enough to hold the largest digest that may be produced by the TPM.
+Because that digest size changes according to the implemented hashes, the maximum amount of
+data returned by this command is TPM implementation-dependent.
+
+Page 126
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+18.1.2 Command and Response
+Table 62 — TPM2_GetRandom Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetRandom
+
+UINT16
+
+bytesRequested
+
+number of octets to return
+
+Table 63 — TPM2_GetRandom Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+randomBytes
+
+Family “2.0”
+Level 00 Revision 00.99
+
+the random octets
+
+Published
+Copyright © TCG 2006-2013
+
+Page 127
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+18.1.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
+#include "InternalRoutines.h"
+#include "GetRandom_fp.h"
+
+TPM_RC
+TPM2_GetRandom(
+GetRandom_In
+GetRandom_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// if the requested bytes exceed the output buffer size, generates the
+// maximum bytes that the output buffer allows
+if(in->bytesRequested > sizeof(TPMU_HA))
+out->randomBytes.t.size = sizeof(TPMU_HA);
+else
+out->randomBytes.t.size = in->bytesRequested;
+CryptGenerateRandom(out->randomBytes.t.size, out->randomBytes.t.buffer);
+return TPM_RC_SUCCESS;
+}
+
+Page 128
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+18.2
+
+Part 3: Commands
+
+TPM2_StirRandom
+
+18.2.1 General Description
+This command is used to add "additional information" to the RNG state.
+NOTE
+
+The "additional information" is as defined in SP800 -90A.
+
+The inData parameter may not be larger than 128 octets.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 129
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+18.2.2 Command and Response
+Table 64 — TPM2_StirRandom Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_StirRandom {NV}
+
+TPM2B_SENSITIVE_DATA
+
+inData
+
+additional information
+
+Table 65 — TPM2_StirRandom Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 130
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+18.2.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+#include "InternalRoutines.h"
+#include "StirRandom_fp.h"
+
+TPM_RC
+TPM2_StirRandom(
+StirRandom_In
+*in
+// IN: input parameter list
+)
+{
+// Internal Data Update
+CryptStirRandom(in->inData.t.size, in->inData.t.buffer);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 131
+October 31, 2013
+
+ Part 3: Commands
+
+19
+
+Trusted Platform Module Library
+
+Hash/HMAC/Event Sequences
+
+19.1
+
+Introduction
+
+All of the commands in this group are to support sequences for which an intermediate state must be
+maintained. For a description of sequences, see “Hash, HMAC, and Event Sequences” in Part 1.
+19.2
+
+TPM2_HMAC_Start
+
+19.2.1 General Description
+This command starts an HMAC sequence. The TPM will create and initialize an HMAC sequence
+structure, assign a handle to the sequence, and set the authValue of the sequence object to the value in
+auth.
+NOTE 1
+
+The structure of a sequence object is vendor -dependent.
+
+The caller shall provide proper authorization for use of handle.
+If the sign attribute is not SET in the key referenced by handle then the TPM shall return
+TPM_RC_ATTRIBUTES. If the key type is not TPM_ALG_KEYEDHASH then the TPM shall return
+TPM_RC_TYPE.
+If handle references a restricted key, then the hash algorithm specified in the key's scheme is used as the
+hash algorithm for the HMAC and the TPM shall return TPM_RC_VALUE if hashAlg is not
+TPM_ALG_NULL or the same algorithm in the key's scheme.
+If the key referenced by handle is not restricted, then the TPM will use hashAlg for the HMAC; unless
+hashAlg is TPM_ALG_NULL in which case it will use the default scheme of the key.
+Table 66 — Hash Selection Matrix
+handle→restricted
+(key's restricted
+attribute)
+
+handle→scheme
+(hash algorithm
+from key's scheme)
+
+CLEAR (unrestricted)
+
+TPM_ALG_NULL
+
+CLEAR
+
+don’t care
+
+CLEAR
+
+valid hash
+
+hash used
+
+TPM_ALG_NULL
+
+error
+
+valid hash
+
+(1)
+
+hashAlg
+
+hashAlg
+
+(2)
+
+(TPM_RC_SCHEME)
+
+TPM_ALG_NULL
+
+handle→scheme
+
+same as handle→scheme
+
+handle→scheme
+
+(3)
+
+SET
+
+handle→scheme
+
+(3)
+
+SET (restricted)
+
+TPM_ALG_NULL
+
+(3)
+
+not same as
+handle→scheme
+
+error
+
+valid hash
+valid hash
+
+SET
+
+valid hash
+
+(4)
+
+(TPM_RC_SCHEME)
+
+NOTES:
+1)
+
+The scheme for the handle may only be TPM_ALG_NULL if both sign and decrypt are SET.
+
+2)
+
+A hash algorithm is required for the HMAC.
+
+3)
+
+A restricted key is required to have a scheme with a valid hash algorithm. A restricted key may not have both sign and
+decrypt SET.
+
+4)
+
+The scheme for a restricted key cannot be overridden.
+
+Page 132
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.2.2 Command and Response
+Table 67 — TPM2_HMAC_Start Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HMAC_Start
+
+TPMI_DH_OBJECT
+
+@handle
+
+handle of an HMAC key
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_AUTH
+
+auth
+
+authorization value for subsequent use of the sequence
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+the hash algorithm to use for the HMAC
+
+Table 68 — TPM2_HMAC_Start Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_DH_OBJECT
+
+sequenceHandle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+a handle to reference the sequence
+
+Published
+Copyright © TCG 2006-2013
+
+Page 133
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HMAC_Start_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by handle is not a signing key
+
+TPM_RC_OBJECT_MEMORY
+
+no space to create an internal object
+
+TPM_RC_TYPE
+
+key referenced by handle is not an HMAC key
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
+Meaning
+
+hashAlg specified when the key is restricted is neither
+TPM_ALG_NULL not equal to that of the key scheme; or both
+hashAlg and the key scheme's algorithm are TPM_ALG_NULL
+
+TPM_RC
+TPM2_HMAC_Start(
+HMAC_Start_In
+HMAC_Start_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+TPMT_PUBLIC
+TPM_ALG_ID
+
+*hmacObject;
+*publicArea;
+hashAlg;
+
+// Input Validation
+// Get HMAC key object and public area pointers
+hmacObject = ObjectGet(in->handle);
+publicArea = &hmacObject->publicArea;
+// Make sure that the key is an HMAC signing key
+if(publicArea->type != TPM_ALG_KEYEDHASH)
+return TPM_RC_TYPE + RC_HMAC_Start_handle;
+if(publicArea->objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_HMAC_Start_handle;
+// Assume that the key default scheme is used
+hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
+// if the key is restricted, then need to use the scheme of the key and the
+// input algorithm must be TPM_ALG_NULL or the same as the key scheme
+if(publicArea->objectAttributes.restricted == SET)
+{
+if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
+hashAlg = TPM_ALG_NULL;
+}
+else
+{
+// for a non-restricted key, use hashAlg if it is provided;
+if(in->hashAlg != TPM_ALG_NULL)
+hashAlg = in->hashAlg;
+}
+// if the algorithm selection ended up with TPM_ALG_NULL, then either the
+// schemes are not compatible or no hash was provided and both conditions
+// are errors.
+if(hashAlg == TPM_ALG_NULL)
+return TPM_RC_VALUE + RC_HMAC_Start_hashAlg;
+// Internal Data Update
+
+Page 134
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+48
+49
+50
+51
+52
+53
+54
+55
+
+Part 3: Commands
+
+// Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
+// returned at this point
+return ObjectCreateHMACSequence(hashAlg,
+in->handle,
+&in->auth,
+&out->sequenceHandle);
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 135
+October 31, 2013
+
+ Part 3: Commands
+
+19.3
+
+Trusted Platform Module Library
+
+TPM2_HashSequenceStart
+
+19.3.1 General Description
+This command starts a hash or an Event sequence. If hashAlg is an implemented hash, then a hash
+sequence is started. If hashAlg is TPM_ALG_NULL, then an Event sequence is started. If hashAlg is
+neither an implemented algorithm nor TPM_ALG_NULL, then the TPM shall return TPM_RC_HASH.
+Depending on hashAlg, the TPM will create and initialize a hash sequence structure or an Event
+sequence structure. Additionally, it will assign a handle to the sequence and set the authValue of the
+sequence to the value in auth. A sequence structure for an Event (hashAlg = TPM_ALG_NULL) contains
+a hash context for each of the PCR banks implemented on the TPM.
+
+Page 136
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.3.2 Command and Response
+Table 69 — TPM2_HashSequenceStart Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HashSequenceStart
+
+TPM2B_AUTH
+
+auth
+
+authorization value for subsequent use of the sequence
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+the hash algorithm to use for the hash sequence
+An Event sequence starts if this is TPM_ALG_NULL.
+
+Table 70 — TPM2_HashSequenceStart Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_DH_OBJECT
+
+sequenceHandle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+a handle to reference the sequence
+
+Published
+Copyright © TCG 2006-2013
+
+Page 137
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HashSequenceStart_fp.h"
+Error Returns
+TPM_RC_OBJECT_MEMORY
+
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
+Meaning
+no space to create an internal object
+
+TPM_RC
+TPM2_HashSequenceStart(
+HashSequenceStart_In
+HashSequenceStart_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Internal Data Update
+if(in->hashAlg == TPM_ALG_NULL)
+// Start a event sequence. A TPM_RC_OBJECT_MEMORY error may be
+// returned at this point
+return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle);
+// Start a hash sequence. A TPM_RC_OBJECT_MEMORY error may be
+// returned at this point
+return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle);
+}
+
+Page 138
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+19.4
+
+Part 3: Commands
+
+TPM2_SequenceUpdate
+
+19.4.1 General Description
+This command is used to add data to a hash or HMAC sequence. The amount of data in buffer may be
+any size up to the limits of the TPM.
+NOTE
+
+In all TPM, a buffer size of 1,024 octets is allowed.
+
+Proper authorization for the sequence object associated with sequenceHandle is required. If an
+authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
+associated with sequenceHandle will be the Empty Buffer.
+If the command does not return TPM_RC_SUCCESS, the state of the sequence is unmodified.
+If the sequence is intended to produce a digest that will be signed by a restricted signing key, then the
+first block of data shall contain sizeof(TPM_GENERATED) octets and the first octets shall not be
+TPM_GENERATED_VALUE.
+NOTE
+
+This requirement allows the TPM to validate that the first block is safe to sign without having to
+accumulate octets over multiple calls.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 139
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.4.2 Command and Response
+Table 71 — TPM2_SequenceUpdate Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SequenceUpdate
+
+TPMI_DH_OBJECT
+
+@sequenceHandle
+
+handle for the sequence object
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+data to be added to hash
+
+Table 72 — TPM2_SequenceUpdate Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 140
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "SequenceUpdate_fp.h"
+Error Returns
+TPM_RC_MODE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+sequenceHandle does not reference a hash or HMAC sequence
+object
+
+TPM_RC
+TPM2_SequenceUpdate(
+SequenceUpdate_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+OBJECT
+
+*object;
+
+// Input Validation
+// Get sequence object pointer
+object = ObjectGet(in->sequenceHandle);
+// Check that referenced object is a sequence object.
+if(!ObjectIsSequence(object))
+return TPM_RC_MODE + RC_SequenceUpdate_sequenceHandle;
+// Internal Data Update
+if(object->attributes.eventSeq == SET)
+{
+// Update event sequence object
+UINT32
+i;
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+for(i = 0; i < HASH_COUNT; i++)
+{
+// Update sequence object
+CryptUpdateDigest2B(&hashObject->state.hashState[i], &in->buffer.b);
+}
+}
+else
+{
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+// Update hash/HMAC sequence object
+if(hashObject->attributes.hashSeq == SET)
+{
+// Is this the first block of the sequence
+if(hashObject->attributes.firstBlock == CLEAR)
+{
+// If so, indicate that first block was received
+hashObject->attributes.firstBlock = SET;
+// Check the first block to see if the first block can contain
+// the TPM_GENERATED_VALUE. If it does, it is not safe for
+// a ticket.
+if(TicketIsSafe(&in->buffer.b))
+hashObject->attributes.ticketSafe = SET;
+}
+// Update sequence object hash/HMAC stack
+CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 141
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+
+Trusted Platform Module Library
+
+}
+else if(object->attributes.hmacSeq == SET)
+{
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+// Update sequence object hash/HMAC stack
+CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b);
+}
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 142
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+19.5
+
+Part 3: Commands
+
+TPM2_SequenceComplete
+
+19.5.1 General Description
+This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
+NOTE 1
+
+This command is not used to complete an Event sequence. TPM2_EventSequenceComplete() is
+used for that purpose.
+
+For a hash sequence, if the results of the hash will be used in a signing operation that uses a restricted
+signing key, then the ticket returned by this command can indicate that the hash is safe to sign.
+If the digest is not safe to sign, then validation will be a TPMT_TK_HASHCHECK with the hierarchy set to
+TPM_RH_NULL and digest set to the Empty Buffer.
+NOTE 2
+
+Regardless of the contents of the first octets of the hashed message, if the first buffer sent to the
+TPM had fewer than sizeof(TPM_GENERATED) octets, then the TPM will operate as if digest is not
+safe to sign.
+
+If sequenceHandle references an Event sequence, then the TPM shall return TPM_RC_MODE.
+Proper authorization for the sequence object associated with sequenceHandle is required. If an
+authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
+associated with sequenceHandle will be the Empty Buffer.
+If this command completes successfully, the sequenceHandle object will be flushed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 143
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.5.2 Command and Response
+Table 73 — TPM2_SequenceComplete Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SequenceComplete {F}
+
+TPMI_DH_OBJECT
+
+@sequenceHandle
+
+authorization for the sequence
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+data to be added to the hash/HMAC
+
+TPMI_RH_HIERARCHY+
+
+hierarchy
+
+hierarchy of the ticket for a hash
+
+Table 74 — TPM2_SequenceComplete Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+result
+
+the returned HMAC or digest in a sized buffer
+
+validation
+
+ticket indicating that the sequence of octets used to
+compute outDigest did not start with
+TPM_GENERATED_VALUE
+This is a NULL Ticket when the session is HMAC.
+
+TPMT_TK_HASHCHECK
+
+Page 144
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "SequenceComplete_fp.h"
+#include <Platform.h>
+Error Returns
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+sequenceHandle does not reference a hash or HMAC sequence
+object
+
+TPM_RC
+TPM2_SequenceComplete(
+SequenceComplete_In
+SequenceComplete_Out
+
+*in,
+*out
+
+OBJECT
+
+// IN: input parameter list
+// OUT: output parameter list
+
+*object;
+
+)
+{
+// Input validation
+// Get hash object pointer
+object = ObjectGet(in->sequenceHandle);
+// input handle must be a hash or HMAC sequence object.
+if(
+object->attributes.hashSeq == CLEAR
+&& object->attributes.hmacSeq == CLEAR)
+return TPM_RC_MODE + RC_SequenceComplete_sequenceHandle;
+// Command Output
+if(object->attributes.hashSeq == SET)
+// sequence object for hash
+{
+// Update last piece of data
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b);
+// Complete hash
+out->result.t.size
+= CryptGetHashDigestSize(
+CryptGetContextAlg(&hashObject->state.hashState[0]));
+CryptCompleteHash2B(&hashObject->state.hashState[0], &out->result.b);
+// Check if the first block of the sequence has been received
+if(hashObject->attributes.firstBlock == CLEAR)
+{
+// If not, then this is the first block so see if it is 'safe'
+// to sign.
+if(TicketIsSafe(&in->buffer.b))
+hashObject->attributes.ticketSafe = SET;
+}
+// Output ticket
+out->validation.tag = TPM_ST_HASHCHECK;
+out->validation.hierarchy = in->hierarchy;
+if(in->hierarchy == TPM_RH_NULL)
+{
+// Ticket is not required
+out->validation.digest.t.size = 0;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 145
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+
+Trusted Platform Module Library
+
+}
+else if(object->attributes.ticketSafe == CLEAR)
+{
+// Ticket is not safe to generate
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else
+{
+// Compute ticket
+TicketComputeHashCheck(out->validation.hierarchy,
+&out->result, &out->validation);
+}
+}
+else
+{
+HASH_OBJECT
+
+*hashObject = (HASH_OBJECT *)object;
+
+//
+Update last piece of data
+CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b);
+// Complete hash/HMAC
+out->result.t.size =
+CryptGetHashDigestSize(
+CryptGetContextAlg(&hashObject->state.hmacState.hashState));
+CryptCompleteHMAC2B(&(hashObject->state.hmacState), &out->result.b);
+// No ticket is generated for HMAC sequence
+out->validation.tag = TPM_ST_HASHCHECK;
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+// Internal Data Update
+// mark sequence object as evict so it will be flushed on the way out
+object->attributes.evict = SET;
+return TPM_RC_SUCCESS;
+}
+
+Page 146
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+19.6
+
+Part 3: Commands
+
+TPM2_EventSequenceComplete
+
+19.6.1 General Description
+This command adds the last part of data, if any, to an Event sequence and returns the result in a digest
+list. If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in
+the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each
+bank extended with the associated digest value.
+If sequenceHandle references a hash or HMAC sequence, the TPM shall return TPM_RC_MODE.
+Proper authorization for the sequence object associated with sequenceHandle is required. If an
+authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
+associated with sequenceHandle will be the Empty Buffer.
+If this command completes successfully, the sequenceHandle object will be flushed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 147
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.6.2 Command and Response
+Table 75 — TPM2_EventSequenceComplete Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EventSequenceComplete {NV F}
+
+@ pcrHandle
+
+PCR to be extended with the Event data
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+@sequenceHandle
+
+authorization for the sequence
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+data to be added to the Event
+
+TPMI_DH_PCR+
+
+Description
+
+Table 76 — TPM2_EventSequenceComplete Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPML_DIGEST_VALUES
+
+results
+
+Page 148
+October 31, 2013
+
+list of digests computed for the PCR
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.6.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "EventSequenceComplete_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+PCR extension is not allowed at the current locality
+
+TPM_RC_MODE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+input handle is not a valid event sequence object
+
+TPM_RC
+TPM2_EventSequenceComplete(
+EventSequenceComplete_In
+EventSequenceComplete_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+HASH_OBJECT
+UINT32
+TPM_ALG_ID
+
+result;
+*hashObject;
+i;
+hashAlg;
+
+// Input validation
+// get the event sequence object pointer
+hashObject = (HASH_OBJECT *)ObjectGet(in->sequenceHandle);
+// input handle must reference an event sequence object
+if(hashObject->attributes.eventSeq != SET)
+return TPM_RC_MODE + RC_EventSequenceComplete_sequenceHandle;
+// see if a PCR extend is requested in call
+if(in->pcrHandle != TPM_RH_NULL)
+{
+// see if extend of the PCR is allowed at the locality of the command,
+if(!PCRIsExtendAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// if an extend is going to take place, then check to see if there has
+// been an orderly shutdown. If so, and the selected PCR is one of the
+// state saved PCR, then the orderly state has to change. The orderly state
+// does not change for PCR that are not preserved.
+// NOTE: This doesn't just check for Shutdown(STATE) because the orderly
+// state will have to change if this is a state-saved PCR regardless
+// of the current state. This is because a subsequent Shutdown(STATE) will
+// check to see if there was an orderly shutdown and not do anything if
+// there was. So, this must indicate that a future Shutdown(STATE) has
+// something to do.
+if(gp.orderlyState != SHUTDOWN_NONE && PCRIsStateSaved(in->pcrHandle))
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+}
+// Command Output
+out->results.count = 0;
+for(i = 0; i < HASH_COUNT; i++)
+{
+hashAlg = CryptGetHashAlgByIndex(i);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 149
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+Trusted Platform Module Library
+
+// Update last piece of data
+CryptUpdateDigest2B(&hashObject->state.hashState[i], &in->buffer.b);
+// Complete hash
+out->results.digests[out->results.count].hashAlg = hashAlg;
+CryptCompleteHash(&hashObject->state.hashState[i],
+CryptGetHashDigestSize(hashAlg),
+(BYTE *) &out->results.digests[out->results.count].digest);
+// Extend PCR
+if(in->pcrHandle != TPM_RH_NULL)
+PCRExtend(in->pcrHandle, hashAlg,
+CryptGetHashDigestSize(hashAlg),
+(BYTE *) &out->results.digests[out->results.count].digest);
+out->results.count++;
+}
+// Internal Data Update
+// mark sequence object as evict so it will be flushed on the way out
+hashObject->attributes.evict = SET;
+return TPM_RC_SUCCESS;
+}
+
+Page 150
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Attestation Commands
+
+20
+20.1
+
+Introduction
+
+The attestation commands cause the TPM to sign an internally generated data structure. The contents of
+the data structure vary according to the command.
+For all signing commands, provisions are made for the caller to provide a scheme to be used for the
+signing operation. This scheme will be applied only if the scheme of the key is TPM_ALG_NULL. If the
+scheme for signHandle is not TPM_ALG_NULL, then inScheme.scheme shall be TPM_ALG_NULL or the
+same as scheme in the public area of the key. If the scheme for signHandle is TPM_ALG_NULL, then
+inScheme will be used for the signing operation and may not be TPM_ALG_NULL. The TPM shall return
+TPM_RC_SCHEME to indicate that the scheme is not appropriate.
+For a signing key that is not restricted, the caller may specify the scheme to be used as long as the
+scheme is compatible with the family of the key (for example, TPM_ALG_RSAPSS cannot be selected for
+an ECC key). If the caller sets scheme to TPM_ALG_NULL, then the default scheme of the key is used.
+If the handle for the signing key (signHandle) is TPM_RH_NULL, then all of the actions of the command
+are performed and the attestation block is “signed” with the NULL Signature.
+NOTE 1
+
+This mechanism is provided so that additional commands are not required to access the data that
+might be in an attestation structure.
+
+NOTE 2
+
+When signHandle is TPM_RH_NULL, scheme is still required to be a valid signing scheme (may be
+TPM_ALG_NULL), but the scheme will have no effect on the format of the signature. It will always
+be the NULL Signature.
+
+TPM2_NV_Certify() is an attestation command that is documented in 1. The remaining attestation
+commands are collected in the remainder of this clause.
+Each of the attestation structures contains a TPMS_CLOCK_INFO structure and a firmware version
+number. These values may be considered privacy-sensitive, because they would aid in the correlation of
+attestations by different keys. To provide improved privacy, the resetCount, restartCount, and
+firmwareVersion numbers are obfuscated when the signing key is not in the Endorsement or Platform
+hierarchies.
+The obfuscation value is computed by:
+
+obfuscation ≔ KDFa(signHandle→nameAlg, shProof, “OBFUSCATE”, signHandle→QN, 0, 128) (3)
+Of the returned 128 bits, 64 bits are added to the versionNumber field of the attestation structure; 32 bits
+are added to the clockInfo.resetCount and 32 bits are added to the clockInfo.restartCount. The order in
+which the bits are added is implementation-dependent.
+NOTE 3
+
+The obfuscation value for each signing key will be unique to that key in a specific location. That is,
+each version of a duplicated signing key will have a different obfuscation value.
+
+When the signing key is TPM_RH_NULL, the data structure is produced but not signed; and the values in
+the signed data structure are obfuscated. When computing the obfuscation value for TPM_RH_NULL, the
+hash used for context integrity is used.
+NOTE 4
+
+The QN for TPM_RH_NULL is TPM_RH_NULL.
+
+If the signing scheme of signHandle is an anonymous scheme, then the attestation blocks will not contain
+the Qualified Name of the signHandle.
+Each of the attestation structures allows the caller to provide some qualifying data (qualifyingData). For
+most signing schemes, this value will be placed in the TPMS_ATTEST.extraData parameter that is then
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 151
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+hashed and signed. However, for some schemes such as ECDAA, the qualifyingData is used in a
+different manner (for details, see “ECDAA” in Part 1).
+
+Page 152
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.2
+
+Part 3: Commands
+
+TPM2_Certify
+
+20.2.1 General Description
+The purpose of this command is to prove that an object with a specific Name is loaded in the TPM. By
+certifying that the object is loaded, the TPM warrants that a public area with a given Name is selfconsistent and associated with a valid sensitive area. If a relying party has a public area that has the
+same Name as a Name certified with this command, then the values in that public area are correct.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+Authorization for objectHandle requires ADMIN role authorization. If performed with a policy session, the
+session shall have a policySession→commandCode set to TPM_CC_Certify. This indicates that the
+policy that is being used is a policy that is for certification, and not a policy that would approve another
+use. That is, authority to use an object does not grant authority to certify the object.
+The object may be any object that is loaded with TPM2_Load() or TPM2_CreatePrimary(). An object that
+only has its public area loaded cannot be certified.
+NOTE 2
+
+The restriction occurs because the Name is used to identify the object being certified. If the TPM
+has not validated that the public area is associated with a matched sensitive area, then the public
+area may not represent a valid object a nd cannot be certified.
+
+The certification includes the Name and Qualified Name of the certified object as well as the Name and
+the Qualified Name of the certifying object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 153
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.2.2 Command and Response
+Table 77 — TPM2_Certify Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Certify
+
+@objectHandle
+
+handle of the object to be certified
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the key used to sign the attestation structure
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+user provided qualifying data
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPMI_DH_OBJECT
+
+Description
+
+Table 78 — TPM2_Certify Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+.
+
+TPM2B_ATTEST
+
+certifyInfo
+
+the structure that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the asymmetric signature over certifyInfo using the key
+referenced by signHandle
+
+Page 154
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "Certify_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is not compatible with signHandle
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+
+Meaning
+
+digest generated for inScheme is greater or has larger size than the
+modulus of signHandle, or the buffer for the result in signature is too
+small (for an RSA key); invalid commit status (for an ECC key with a
+split scheme).
+
+TPM_RC
+TPM2_Certify(
+Certify_In
+Certify_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMS_ATTEST
+
+result;
+certifyInfo;
+
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&certifyInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_Certify_signHandle;
+else
+return RcSafeAddToResult(result, RC_Certify_inScheme);
+}
+// Certify specific fields
+// Attestation type
+certifyInfo.type = TPM_ST_ATTEST_CERTIFY;
+// Certified object name
+certifyInfo.attested.certify.name.t.size =
+ObjectGetName(in->objectHandle,
+&certifyInfo.attested.certify.name.t.name);
+// Certified object qualified name
+ObjectGetQualifiedName(in->objectHandle,
+&certifyInfo.attested.certify.qualifiedName);
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned
+// by SignAttestInfo()
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&certifyInfo,
+&in->qualifyingData,
+&out->certifyInfo,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 155
+October 31, 2013
+
+ Part 3: Commands
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+
+Trusted Platform Module Library
+&out->signature);
+
+// TPM_RC_ATTRIBUTES cannot be returned here as FillInAttestInfo would already
+// have returned TPM_RC_KEY
+pAssert(result != TPM_RC_ATTRIBUTES);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 156
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.3
+
+Part 3: Commands
+
+TPM2_CertifyCreation
+
+20.3.1 General Description
+This command is used to prove the association between an object and its creation data. The TPM will
+validate that the ticket was produced by the TPM and that the ticket validates the association between a
+loaded public area and the provided hash of the creation data (creationHash).
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+The TPM will create a test ticket using the Name associated with objectHandle and creationHash as:
+
+HMAC(proof, (TPM_ST_CREATION || objectHandle→Name || creationHash))
+
+(4)
+
+This ticket is then compared to creation ticket. If the tickets are not the same, the TPM shall return
+TPM_RC_TICKET.
+If the ticket is valid, then the TPM will create a TPMS_ATTEST structure and place creationHash of the
+command in the creationHash field of the structure. The Name associated with objectHandle will be
+included in the attestation data that is then signed using the key associated with signHandle.
+NOTE 2
+
+If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
+Signature.
+
+ObjectHandle may be any object that is loaded with TPM2_Load() or TPM2_CreatePrimary().
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 157
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.3.2 Command and Response
+Table 79 — TPM2_CertifyCreation Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_CertifyCreation
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the key that will sign the attestation block
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+objectHandle
+
+the object associated with the creation data
+Auth Index: None
+
+TPM2B_DATA
+
+qualifyingData
+
+user-provided qualifying data
+
+TPM2B_DIGEST
+
+creationHash
+
+hash of the creation data produced by TPM2_Create()
+or TPM2_CreatePrimary()
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPMT_TK_CREATION
+
+creationTicket
+
+ticket produced by TPM2_Create() or
+TPM2_CreatePrimary()
+
+Table 80 — TPM2_CertifyCreation Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+certifyInfo
+
+the structure that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over certifyInfo
+
+Page 158
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "CertifyCreation_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is not compatible with signHandle
+
+TPM_RC_TICKET
+
+creationTicket does not match objectHandle
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+digest generated for inScheme is greater or has larger size than the
+modulus of signHandle, or the buffer for the result in signature is too
+small (for an RSA key); invalid commit status (for an ECC key with a
+split scheme).
+
+TPM_RC
+TPM2_CertifyCreation(
+CertifyCreation_In
+CertifyCreation_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPM2B_NAME
+TPMT_TK_CREATION
+TPMS_ATTEST
+
+result;
+name;
+ticket;
+certifyInfo;
+
+// Input Validation
+// CertifyCreation specific input validation
+// Get certified object name
+name.t.size = ObjectGetName(in->objectHandle, &name.t.name);
+// Re-compute ticket
+TicketComputeCreation(in->creationTicket.hierarchy, &name,
+&in->creationHash, &ticket);
+// Compare ticket
+if(!Memory2BEqual(&ticket.digest.b, &in->creationTicket.digest.b))
+return TPM_RC_TICKET + RC_CertifyCreation_creationTicket;
+// Command Output
+// Common fields
+result = FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
+&certifyInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_CertifyCreation_signHandle;
+else
+return RcSafeAddToResult(result, RC_CertifyCreation_inScheme);
+}
+// CertifyCreation specific fields
+// Attestation type
+certifyInfo.type = TPM_ST_ATTEST_CREATION;
+certifyInfo.attested.creation.objectName = name;
+// Copy the creationHash
+certifyInfo.attested.creation.creationHash = in->creationHash;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 159
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+
+Trusted Platform Module Library
+
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+// this point
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&certifyInfo,
+&in->qualifyingData,
+&out->certifyInfo,
+&out->signature);
+// TPM_RC_ATTRIBUTES cannot be returned here as FillInAttestInfo would already
+// have returned TPM_RC_KEY
+pAssert(result != TPM_RC_ATTRIBUTES);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 160
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.4
+
+Part 3: Commands
+
+TPM2_Quote
+
+20.4.1 General Description
+This command is used to quote PCR values.
+NOTE
+
+See 20.1 for description of how the signing scheme is selected.
+
+The TPM will hash the list of PCR selected by PCRselect using the hash algorithm associated with
+signHandle (this is the hash algorithm of the signing scheme, not the nameAlg of signHandle).
+The digest is computed as the hash of the concatenation of all of the digest values of the selected PCR.
+The concatenation of PCR is described in Part 1, Selecting Multiple PCR.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 161
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.4.2 Command and Response
+Table 81 — TPM2_Quote Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Quote
+
+TPMI_DH_OBJECT
+
+@signHandle
+
+handle of key that will perform signature
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+data supplied by the caller
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPML_PCR_SELECTION
+
+PCRselect
+
+PCR set to quote
+
+Table 82 — TPM2_Quote Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+quoted
+
+the quoted information
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over quoted
+
+Page 162
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.4.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "Quote_fp.h"
+Error Returns
+TPM_RC_KEY
+
+signHandle does not reference a signing key;
+
+TPM_RC_SCHEME
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+the scheme is not compatible with sign key type, or input scheme is
+not compatible with default scheme, or the chosen scheme is not a
+valid sign scheme
+
+TPM_RC
+TPM2_Quote(
+Quote_In
+Quote_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMI_ALG_HASH
+TPMS_ATTEST
+
+result;
+hashAlg;
+quoted;
+
+// Command Output
+// Filling in attest information
+// Common fields
+// FillInAttestInfo will return TPM_RC_SCHEME or TPM_RC_KEY
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&quoted);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_Quote_signHandle;
+else
+return RcSafeAddToResult(result, RC_Quote_inScheme);
+}
+// Quote specific fields
+// Attestation type
+quoted.type = TPM_ST_ATTEST_QUOTE;
+// Get hash algorithm in sign scheme. This hash algorithm is used to
+// compute PCR digest. If there is no algorithm, then the PCR cannot
+// be digested and this command returns TPM_RC_SCHEME
+hashAlg = in->inScheme.details.any.hashAlg;
+if(hashAlg == TPM_ALG_NULL)
+return TPM_RC_SCHEME + RC_Quote_inScheme;
+// Compute PCR digest
+PCRComputeCurrentDigest(hashAlg,
+&in->PCRselect,
+&quoted.attested.quote.pcrDigest);
+// Copy PCR select. "PCRselect" is modified in PCRComputeCurrentDigest
+// function
+quoted.attested.quote.pcrSelect = in->PCRselect;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 163
+October 31, 2013
+
+ Part 3: Commands
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+
+Trusted Platform Module Library
+
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES
+// error may be returned by SignAttestInfo.
+// NOTE: TPM_RC_ATTRIBUTES means that the key is not a signing key but that
+// was checked above and TPM_RC_KEY was returned. TPM_RC_VALUE means that the
+// value to sign is too large but that means that the digest is too big and
+// that can't happen.
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&quoted,
+&in->qualifyingData,
+&out->quoted,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 164
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.5
+
+Part 3: Commands
+
+TPM2_GetSessionAuditDigest
+
+20.5.1 General Description
+This command returns a digital signature of the audit session digest.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+If sessionHandle is not an audit session, the TPM shall return TPM_RC_TYPE.
+NOTE 2
+
+A session does not become an audit session until the successful completion of the command in
+which the session is first used as an audit session.
+
+This command requires authorization from the privacy administrator of the TPM (expressed with
+endorsementAuth) as well as authorization to use the key associated with signHandle.
+If this command is audited, then the audit digest that is signed will not include the digest of this command
+because the audit digest is only updated when the command completes successfully.
+This command does not cause the audit session to be closed and does not reset the digest value.
+NOTE 3
+
+The audit session digest will be reset if the sessionHandle is used as the audit session for the
+command and the auditReset attribute of the session is set; and this command will be the first
+command in the audit digest.
+
+NOTE 4
+
+A reason for using 'sessionHahdle' in this command is so that the continueSession attribute may be
+CLEAR. This will flush the session at the end of the command.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 165
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.5.2 Command and Response
+Table 83 — TPM2_GetSessionAuditDigest Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetSessionAuditDigest
+
+@privacyAdminHandle
+
+handle of the privacy administrator
+(TPM_RH_ENDORSEMENT)
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the signing key
+Auth Index: 2
+Auth Role: USER
+
+TPMI_SH_HMAC
+
+sessionHandle
+
+handle of the audit session
+Auth Index: None
+
+TPM2B_DATA
+
+qualifyingData
+
+user-provided qualifying data – may be zero-length
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPMI_RH_ENDORSEMENT
+
+Description
+
+Table 84 — TPM2_GetSessionAuditDigest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+auditInfo
+
+the audit information that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over auditInfo
+
+Page 166
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "GetSessionAuditDigest_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is incompatible with signHandle type; or both scheme and
+key's default scheme are empty; or scheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from scheme
+
+TPM_RC_TYPE
+
+sessionHandle does not reference an audit session
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+digest generated for the given scheme is greater than the modulus of
+signHandle (for an RSA key); invalid commit status or failed to
+generate r value (for an ECC key)
+
+TPM_RC
+TPM2_GetSessionAuditDigest(
+GetSessionAuditDigest_In
+GetSessionAuditDigest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+SESSION
+TPMS_ATTEST
+
+result;
+*session;
+auditInfo;
+
+// Input Validation
+// SessionAuditDigest specific input validation
+// Get session pointer
+session = SessionGet(in->sessionHandle);
+// session must be an audit session
+if(session->attributes.isAudit == CLEAR)
+return TPM_RC_TYPE + RC_GetSessionAuditDigest_sessionHandle;
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&auditInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_GetSessionAuditDigest_signHandle;
+else
+return RcSafeAddToResult(result, RC_GetSessionAuditDigest_inScheme);
+}
+// SessionAuditDigest specific fields
+// Attestation type
+auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT;
+// Copy digest
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 167
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+
+Trusted Platform Module Library
+
+auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest;
+// Exclusive audit session
+if(g_exclusiveAuditSession == in->sessionHandle)
+auditInfo.attested.sessionAudit.exclusiveSession = TRUE;
+else
+auditInfo.attested.sessionAudit.exclusiveSession = FALSE;
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+// this point
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&auditInfo,
+&in->qualifyingData,
+&out->auditInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 168
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.6
+
+Part 3: Commands
+
+TPM2_GetCommandAuditDigest
+
+20.6.1 General Description
+This command returns the current value of the command audit digest, a digest of the commands being
+audited, and the audit hash algorithm. These values are placed in an attestation structure and signed with
+the key referenced by signHandle.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+When this command completes successfully, and signHandle is not TPM_RH_NULL, the audit digest is
+cleared.
+NOTE 2
+
+The way that the TPM tracks that the digest is clear is vendor -dependent. The reference
+implementation resets the size of the digest to zero.
+
+If this command is being audited, then the signed digest produced by the command will not include the
+command. At the end of this command, the audit digest will be extended with cpHash and the rpHash of
+the command which would change the command audit digest signed by the next invocation of this
+command.
+This command requires authorization from the privacy administrator of the TPM (expressed with
+endorsementAuth) as well as authorization to use the key associated with signHandle.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 169
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.6.2 Command and Response
+Table 85 — TPM2_GetCommandAuditDigest Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetCommandAuditDigest {NV}
+
+TPMI_RH_ENDORSEMENT
+
+@privacyHandle
+
+handle of the privacy administrator
+(TPM_RH_ENDORSEMENT)
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+the handle of the signing key
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+other data to associate with this audit digest
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+Table 86 — TPM2_GetCommandAuditDigest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+auditInfo
+
+the auditInfo that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over auditInfo
+
+Page 170
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "GetCommandAuditDigest_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is incompatible with signHandle type; or both scheme and
+key's default scheme are empty; or scheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from scheme
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+digest generated for the given scheme is greater than the modulus of
+signHandle (for an RSA key); invalid commit status or failed to
+generate r value (for an ECC key)
+
+TPM_RC
+TPM2_GetCommandAuditDigest(
+GetCommandAuditDigest_In
+GetCommandAuditDigest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMS_ATTEST
+
+result;
+auditInfo;
+
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&auditInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_GetCommandAuditDigest_signHandle;
+else
+return RcSafeAddToResult(result, RC_GetCommandAuditDigest_inScheme);
+}
+// CommandAuditDigest specific fields
+// Attestation type
+auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT;
+// Copy audit hash algorithm
+auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg;
+// Copy counter value
+auditInfo.attested.commandAudit.auditCounter = gp.auditCounter;
+// Copy command audit log
+auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest;
+CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest);
+//
+//
+//
+//
+
+Sign attestation structure. A NULL signature will be returned if
+signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+this point
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 171
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+
+Trusted Platform Module Library
+
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&auditInfo,
+&in->qualifyingData,
+&out->auditInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+if(in->signHandle != TPM_RH_NULL)
+{
+// Reset log
+gr.commandAuditDigest.t.size = 0;
+// orderly state should be cleared because of the update in
+// commandAuditDigest, as well as the reporting of clock info
+g_clearOrderly = TRUE;
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 172
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.7
+
+Part 3: Commands
+
+TPM2_GetTime
+
+20.7.1 General Description
+This command returns the current values of Time and Clock.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+The values of Clock, resetCount and restartCount appear in two places in timeInfo: once in
+TPMS_ATTEST.clockInfo and again in TPMS_ATTEST.attested.time.clockInfo. The firmware version
+number
+also
+appears
+in
+two
+places
+(TPMS_ATTEST.firmwareVersion
+and
+TPMS_ATTEST.attested.time.firmwareVersion). If signHandle is in the endorsement or platform
+hierarchies, both copies of the data will be the same. However, if signHandle is in the storage hierarchy or
+is TPM_RH_NULL, the values in TPMS_ATTEST.clockInfo and TPMS_ATTEST.firmwareVersion are
+obfuscated but the values in TPM_ATTEST.attested.time are not.
+NOTE 2
+
+The purpose of this duplication is to allow an entity who is trusted by the privacy Administrator to
+correlate the obfuscated values with the clear -text values.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 173
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.7.2 Command and Response
+Table 87 — TPM2_GetTime Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetTime
+
+@privacyAdminHandle
+
+handle of the privacy administrator
+(TPM_RH_ENDORSEMENT)
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+the keyHandle identifier of a loaded key that can
+perform digital signatures
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+data to tick stamp
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPMI_RH_ENDORSEMENT
+
+Description
+
+Table 88 — TPM2_GetTime Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+.
+
+TPM2B_ATTEST
+
+timeInfo
+
+standard TPM-generated attestation block
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over timeInfo
+
+Page 174
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.7.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "GetTime_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is incompatible with signHandle type; or both scheme and
+key's default scheme are empty; or scheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from scheme
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+digest generated for the given scheme is greater than the modulus of
+signHandle (for an RSA key); invalid commit status or failed to
+generate r value (for an ECC key)
+
+TPM_RC
+TPM2_GetTime(
+GetTime_In
+GetTime_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMS_ATTEST
+
+result;
+timeInfo;
+
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&timeInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_GetTime_signHandle;
+else
+return RcSafeAddToResult(result, RC_GetTime_inScheme);
+}
+// GetClock specific fields
+// Attestation type
+timeInfo.type = TPM_ST_ATTEST_TIME;
+// current clock in plain text
+timeInfo.attested.time.time.time = g_time;
+TimeFillInfo(&timeInfo.attested.time.time.clockInfo);
+// Firmware version in plain text
+timeInfo.attested.time.firmwareVersion
+= ((UINT64) gp.firmwareV1) << 32;
+timeInfo.attested.time.firmwareVersion += gp.firmwareV2;
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+// this point
+result = SignAttestInfo(in->signHandle,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 175
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+Trusted Platform Module Library
+
+&in->inScheme,
+&timeInfo,
+&in->qualifyingData,
+&out->timeInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 176
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+21
+
+Part 3: Commands
+
+Ephemeral EC Keys
+
+21.1
+
+Introduction
+
+The TPM generates keys that have different lifetimes. TPM keys in a hierarchy can be persistent for as
+long as the seed of the hierarchy is unchanged and these keys may be used multiple times. Other TPMgenerated keys are only useful for a single operation. Some of these single-use keys are used in the
+command in which they are created. Examples of this use are TPM2_Duplicate() where an ephemeral
+key is created for a single pass key exchange with another TPM. However, there are other cases, such
+as anonymous attestation, where the protocol requires two passes where the public part of the ephemeral
+key is used outside of the TPM before the final command "consumes" the ephemeral key.
+For these uses, TPM2_Commit() or TPM2_EC_Ephemeral() may be used to have the TPM create an
+ephemeral EC key and return the public part of the key for external use. Then in a subsequent command,
+the caller provides a reference to the ephemeral key so that the TPM can retrieve or recreate the
+associated private key.
+When an ephemeral EC key is created, it is assigned a number and that number is returned to the caller
+as the identifier for the key. This number is not a handle. A handle is assigned to a key that may be
+context saved but these ephemeral EC keys may not be saved and do not have a full key context. When
+a subsequent command uses the ephemeral key, the caller provides the number of the ephemeral key.
+The TPM uses that number to either look up or recompute the associated private key. After the key is
+used, the TPM records the fact that the key has been used so that it cannot be used again.
+As mentioned, the TPM can keep each assigned private ephemeral key in memory until it is used.
+However, this could consume a large amount of memory. To limit the memory size, the TPM is allowed to
+restrict the number of pending private keys – keys that have been allocated but not used.
+NOTE
+
+The minimum number of ephemeral keys is determined by a platform specific specification
+
+To further reduce the memory requirements for the ephemeral private keys, the TPM is allowed to use
+pseudo-random values for the ephemeral keys. Instead of keeping the full value of the key in memory, the
+TPM can use a counter as input to a KDF. Incrementing the counter will cause the TPM to generate a
+new pseudo-random value.
+Using the counter to generate pseudo-random private ephemeral keys greatly simplifies tracking of key
+usage. When a counter value is used to create a key, a bit in an array may be set to indicate that the key
+use is pending. When the ephemeral key is consumed, the bit is cleared. This prevents the key from
+being used more than once.
+Since the TPM is allowed to restrict the number of pending ephemeral keys, the array size can be limited.
+For example, a 128 bit array would allow 128 keys to be "pending".
+The management of the array is described in greater detail in the Split Operations clause in Annex C of
+part 1.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 177
+October 31, 2013
+
+ Part 3: Commands
+
+21.2
+
+Trusted Platform Module Library
+
+TPM2_Commit
+
+21.2.1 General Description
+TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM will perform
+the point multiplications on the provided points and return intermediate signing values. The signHandle
+parameter shall refer to an ECC key with the sign attribute (TPM_RC_ATTRIBUTES) using an
+anonymous signing scheme (TPM_RC_SCHEME).
+For this command, p1, s2 and y2 are optional parameters. If s2 is an Empty Buffer, then the TPM shall
+return TPM_RC_SIZE if y2 is not an Empty Buffer. If p1, s2, and y2 are all Empty Buffers, the TPM shall
+return TPM_RC_NO_RESULT.
+In the algorithm below, the following additional values are used in addition to the command parameters:
+
+HnameAlg
+
+hash function using the nameAlg of the key associated with
+signHandle
+
+p
+
+field modulus of the curve associated with signHandle
+
+n
+
+order of the curve associated with signHandle
+
+ds
+
+private key associated with signHandle
+
+c
+
+counter that increments each time a TPM2_Commit() is
+successfully completed
+
+A[i]
+
+array of bits used to indicate when a value of c has been used in
+a signing operation; values of i are 0 to 2n-1
+
+k
+
+nonce that is set to a random value on each TPM Reset; nonce
+size is twice the security strength of any ECDAA key supported
+by the TPM.
+
+The algorithm is:
+a) set K, L, and E to be Empty Buffers.
+b) if s2 is not an Empty Buffer, compute x2 ≔ HnameAlg (s2) mod p, else skip to step (e)
+c) if (x2, y2) is not a point on the curve of signHandle, return TPM_RC_ECC_POINT
+d) set K ≔ [ds] (x2, y2)
+e) generate or derive r (see the "Commit Random Value" clause in Part 1)
+f)
+
+set r ≔ r mod n
+
+NOTE 1
+
+nLen is the number of bits in n
+
+g) if p1 is an Empty Buffer, skip to step i)
+h) if (p1) is not a point on the curve of signHandle, return TPM_RC_ECC_POINT
+i)
+
+set E ≔ [r] (p1)
+
+j)
+
+if K is not an Empty Buffer, set L ≔ [r] (x2, y2)
+
+k) if K, L, or E is the point at infinity, return TPM_RC_NO_RESULT
+l)
+
+set counter ≔ commitCount
+
+m) set commitCount ≔ commitCount + 1
+
+Page 178
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+NOTE 2
+
+Part 3: Commands
+
+Depending on the method of generating r, it may be necessary to update the tracking array here.
+
+n) output K, L, E and counter
+NOTE 3
+
+Depending on the input parameters K and L may be Empty Buffers or E may be an Empty Buffer
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 179
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+21.2.2 Command and Response
+Table 89 — TPM2_Commit Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+paramSize
+
+TPM_CC
+
+commandCode
+
+Description
+
+TPM_CC_Commit
+handle of the key that will be used in the signing
+operation
+
+TPMI_DH_OBJECT
+
+@signHandle
+
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_ECC_POINT
+
+P1
+
+a point (M) on the curve used by signHandle
+
+TPM2B_SENSITIVE_DATA
+
+s2
+
+octet array used to derive x-coordinate of a base point
+
+TPM2B_ECC_PARAMETER
+
+y2
+
+y coordinate of the point associated with s2
+
+Table 90 — TPM2_Commit Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see 8
+
+UINT32
+
+paramSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+K
+
+ECC point K ≔ [ds](x2, y2)
+
+TPM2B_ECC_POINT
+
+L
+
+ECC point L ≔ [r](x2, y2)
+
+TPM2B_ECC_POINT
+
+E
+
+ECC point E ≔ [r]P1
+
+UINT16
+
+counter
+
+least-significant 16 bits of commitCount
+
+Page 180
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+21.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Commit_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_ATTRIBUTES
+
+keyHandle references a restricted key that is not a signing key
+
+TPM_RC_ECC_POINT
+
+either P1 or the point derived from s2 is not on the curve of
+keyHandle
+
+TPM_RC_HASH
+
+invalid name algorithm in keyHandle
+
+TPM_RC_KEY
+
+keyHandle does not reference an ECC key
+
+TPM_RC_SCHEME
+
+keyHandle references a restricted signing key that does not use and
+anonymous scheme
+
+TPM_RC_NO_RESULT
+
+K, L or E was a point at infinity; or failed to generate r value
+
+TPM_RC_SIZE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
+Meaning
+
+s2 is empty but y2 is not or s2 provided but y2 is not
+
+TPM_RC
+TPM2_Commit(
+Commit_In
+Commit_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+TPMS_ECC_POINT
+TPMS_ECC_POINT
+TPMS_ECC_POINT
+TPM2B_ECC_PARAMETER
+TPM2B
+TPM_RC
+UINT16
+
+*eccKey;
+P2;
+*pP2 = NULL;
+*pP1 = NULL;
+r;
+*p;
+result;
+hashResults;
+
+// Input Validation
+eccKey = ObjectGet(in->signHandle);
+// Input key must be an ECC key
+if(eccKey->publicArea.type != TPM_ALG_ECC)
+return TPM_RC_KEY + RC_Commit_signHandle;
+// if the key is restricted, it must be a signing key using an anonymous scheme
+if(eccKey->publicArea.objectAttributes.restricted == SET)
+{
+if(eccKey->publicArea.objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_Commit_signHandle;
+if(!CryptIsSchemeAnonymous(
+eccKey->publicArea.parameters.eccDetail.scheme.scheme))
+return TPM_RC_SCHEME + RC_Commit_signHandle;
+}
+else
+{
+// if not restricted, s2, and y2 must be an Empty Buffer
+if(in->s2.t.size)
+return TPM_RC_SIZE + RC_Commit_s2;
+}
+// Make sure that both parts of P2 are present if either is present
+if((in->s2.t.size == 0) != (in->y2.t.size == 0))
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 181
+October 31, 2013
+
+ Part 3: Commands
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
+Trusted Platform Module Library
+
+return TPM_RC_SIZE + RC_Commit_y2;
+// Get prime modulus for the curve. This is needed later but getting this now
+// allows confirmation that the curve exists
+p = (TPM2B *)CryptEccGetParameter('p',
+eccKey->publicArea.parameters.eccDetail.curveID);
+// if no p, then the curve ID is bad
+// NOTE: This should never occur if the input unmarshaling code is working
+// correctly
+if(p == NULL)
+return TPM_RC_KEY + RC_Commit_signHandle;
+// Get the random value that will be used in the point multiplications
+// Note: this does not commit the count.
+if(!CryptGenerateR(&r,
+NULL,
+eccKey->publicArea.parameters.eccDetail.curveID,
+&eccKey->name))
+return TPM_RC_NO_RESULT;
+// Set up P2 if s2 and Y2 are provided
+if(in->s2.t.size != 0)
+{
+pP2 = &P2;
+// copy y2 for P2
+MemoryCopy2B(&P2.y.b, &in->y2.b, sizeof(P2.y.t.buffer));
+// Compute x2 HnameAlg(s2) mod p
+//
+do the hash operation on s2 with the size of curve 'p'
+hashResults = CryptHashBlock(eccKey->publicArea.nameAlg,
+in->s2.t.size,
+in->s2.t.buffer,
+p->size,
+P2.x.t.buffer);
+// If there were error returns in the hash routine, indicate a problem
+// with the hash in
+if(hashResults == 0)
+return TPM_RC_HASH + RC_Commit_signHandle;
+// set the size of the X value to the size of the hash
+P2.x.t.size = hashResults;
+// set p2.x = hash(s2) mod p
+if(CryptDivide(&P2.x.b, p, NULL, &P2.x.b) != TPM_RC_SUCCESS)
+return TPM_RC_NO_RESULT;
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+pP2))
+return TPM_RC_ECC_POINT + RC_Commit_s2;
+if(eccKey->attributes.publicOnly == SET)
+return TPM_RC_KEY + RC_Commit_signHandle;
+}
+else
+// If there is a P1, make sure that it is on the curve
+// NOTE: an "empty" point has two UINT16 values which are the size values
+// for each of the coordinates.
+if(in->P1.t.size > 4)
+{
+
+Page 182
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+
+Part 3: Commands
+
+pP1 = &in->P1.t.point;
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+pP1))
+return TPM_RC_ECC_POINT + RC_Commit_P1;
+}
+// Pass the parameters to CryptCommit.
+// The work is not done inline because it does several point multiplies
+// with the same curve. There is significant optimization by not
+// having to reload the curve parameters multiple times.
+result = CryptCommitCompute(&out->K.t.point,
+&out->L.t.point,
+&out->E.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+pP1,
+pP2,
+&eccKey->sensitive.sensitive.ecc,
+&r);
+if(result != TPM_RC_SUCCESS)
+return result;
+out->K.t.size = TPMS_ECC_POINT_Marshal(&out->K.t.point, NULL, NULL);
+out->L.t.size = TPMS_ECC_POINT_Marshal(&out->L.t.point, NULL, NULL);
+out->E.t.size = TPMS_ECC_POINT_Marshal(&out->E.t.point, NULL, NULL);
+// The commit computation was successful so complete the commit by setting
+// the bit
+out->counter = CryptCommit();
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 183
+October 31, 2013
+
+ Part 3: Commands
+
+21.3
+
+Trusted Platform Module Library
+
+TPM2_EC_Ephemeral
+
+21.3.1 General Description
+TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol.
+The TPM will use the commit mechanism to assign an ephemeral key r and compute a public point Q ≔
+[r]G where G is the generator point associated with curveID.
+
+Page 184
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+21.3.2 Command and Response
+Table 91 — TPM2_EC_Ephemeral Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+paramSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EC_Ephemeral
+
+TPMI_ECC_CURVE
+
+curveID
+
+The curve for the computed ephemeral point
+
+Table 92 — TPM2_EC_Ephemeral Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see 8
+
+UINT32
+
+paramSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+Q
+
+ephemeral public key Q ≔ [r]G
+
+UINT16
+
+counter
+
+least-significant 16 bits of commitCount
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 185
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+21.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "EC_Ephemeral_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+none
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
+Meaning
+...
+
+TPM_RC
+TPM2_EC_Ephemeral(
+EC_Ephemeral_In
+EC_Ephemeral_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM2B_ECC_PARAMETER
+
+r;
+
+// Get the random value that will be used in the point multiplications
+// Note: this does not commit the count.
+if(!CryptGenerateR(&r,
+NULL,
+in->curveID,
+NULL))
+return TPM_RC_NO_RESULT;
+CryptEccPointMultiply(&out->Q.t.point, in->curveID, &r, NULL);
+// commit the count value
+out->counter = CryptCommit();
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 186
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+22
+
+Part 3: Commands
+
+Signing and Signature Verification
+
+22.1
+
+TPM2_VerifySignature
+
+22.1.1 General Description
+This command uses loaded keys to validate a signature on a message with the message digest passed
+to the TPM.
+If the signature check succeeds, then the TPM will produce a TPMT_TK_VERIFIED. Otherwise, the TPM
+shall return TPM_RC_SIGNATURE.
+NOTE 1
+
+A valid ticket may be used in subsequent commands to provide proof to the TPM that the TPM has
+validated the signature over the message using the key referenced by keyHandle.
+
+If keyHandle references an asymmetric key, only the public portion of the key needs to be loaded. If
+keyHandle references a symmetric key, both the public and private portions need to be loaded.
+NOTE 2
+
+The sensitive area of the symmetric object is required to allow verification of the symmetric
+signature (the HMAC).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 187
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+22.1.2 Command and Response
+Table 93 — TPM2_VerifySignature Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_VerifySignature
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+handle of public key that will be used in the validation
+Auth Index: None
+
+TPM2B_DIGEST
+
+digest
+
+digest of the signed message
+
+TPMT_SIGNATURE
+
+signature
+
+signature to be tested
+
+Table 94 — TPM2_VerifySignature Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMT_TK_VERIFIED
+
+validation
+
+Page 188
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+22.1.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "VerifySignature_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+keyHandle does not reference a signing key
+
+TPM_RC_SIGNATURE
+
+signature is not genuine
+
+TPM_RC_SCHEME
+
+CryptVerifySignature()
+
+TPM_RC_HANDLE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+the input handle is not a sign key with private portion loaded
+
+TPM_RC
+TPM2_VerifySignature(
+VerifySignature_In
+VerifySignature_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+TPM2B_NAME
+OBJECT
+TPMI_RH_HIERARCHY
+
+result;
+name;
+*signObject;
+hierarchy;
+
+)
+{
+
+// Input Validation
+// Get sign object pointer
+signObject = ObjectGet(in->keyHandle);
+// The object to validate the signature must be a signing key.
+if(signObject->publicArea.objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_VerifySignature_keyHandle;
+// If it doesn't have a sensitive area loaded
+// then it can't be a keyed hash signing key
+if(
+signObject->attributes.publicOnly == SET
+&& signObject->publicArea.type == TPM_ALG_KEYEDHASH
+)
+return TPM_RC_HANDLE + RC_VerifySignature_keyHandle;
+// Validate Signature. A TPM_RC_BINDING, TPM_RC_SCHEME or TPM_RC_SIGNATURE
+// error may be returned by CryptCVerifySignatrue()
+result = CryptVerifySignature(in->keyHandle, &in->digest, &in->signature);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_VerifySignature_signature);
+// Command Output
+hierarchy = ObjectGetHierarchy(in->keyHandle);
+if(
+hierarchy == TPM_RH_NULL
+|| signObject->publicArea.nameAlg == TPM_ALG_NULL)
+{
+// produce empty ticket if hierarchy is TPM_RH_NULL or nameAlg is
+// TPM_ALG_NULL
+out->validation.tag = TPM_ST_VERIFIED;
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else
+{
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 189
+October 31, 2013
+
+ Part 3: Commands
+50
+51
+52
+53
+54
+55
+56
+57
+
+Trusted Platform Module Library
+
+// Get object name that verifies the signature
+name.t.size = ObjectGetName(in->keyHandle, &name.t.name);
+// Compute ticket
+TicketComputeVerified(hierarchy, &in->digest, &name, &out->validation);
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 190
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+22.2
+
+Part 3: Commands
+
+TPM2_Sign
+
+22.2.1 General Description
+This command causes the TPM to sign an externally provided hash with the specified asymmetric signing
+key.
+NOTE 1
+
+Symmetric “signing” is done with an HMAC.
+
+If keyHandle references a restricted signing key, then validation shall be provided indicating that the TPM
+performed the hash of the data and validation shall indicate that hashed data did not start with
+TPM_GENERATED_VALUE.
+NOTE 2
+
+If the hashed data did start with TPM_GENERATED_VALUE, then the validation will be a NULL
+ticket.
+
+If the scheme of keyHandle is not TPM_ALG_NULL, then inScheme shall either be the same scheme as
+keyHandle or TPM_ALG_NULL.
+If the scheme of keyHandle is TPM_ALG_NULL, the TPM will sign using inScheme; otherwise, it will sign
+using the scheme of keyHandle.
+NOTE 3
+
+When the signing scheme requires a hash algorithm, the hash is defined in the qualifying data of the
+scheme.
+
+If inScheme is not a valid signing scheme for the type of keyHandle (or TPM_ALG_NULL), then the TPM
+shall return TPM_RC_SCHEME.
+If the scheme of keyHandle is an anonymous scheme, then inScheme shall have the same scheme
+algorithm as keyHandle and inScheme will contain a counter value that will be used in the signing
+process.
+As long as it is no larger than allowed, the digest parameter is not required to have any specific size but
+the signature operation may fail if digest is too large for the selected scheme.
+If the validation parameter is not the Empty Buffer, then it will be checked even if the key referenced by
+keyHandle is not a restricted signing key.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 191
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+22.2.2 Command and Response
+Table 95 — TPM2_Sign Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Sign
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+Handle of key that will perform signing
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+digest
+
+digest to be signed
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for keyHandle is
+TPM_ALG_NULL
+
+validation
+
+proof that digest was created by the TPM
+If keyHandle is not a restricted signing key, then this
+may be a NULL Ticket with tag =
+TPM_ST_CHECKHASH.
+
+TPMT_TK_HASHCHECK
+
+Description
+
+Table 96 — TPM2_Sign Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMT_SIGNATURE
+
+signature
+
+Page 192
+October 31, 2013
+
+the signature
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+22.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Sign_fp.h"
+#include "Attest_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by keHandle is not a signing key
+
+TPM_RC_BINDING
+
+The public and private portions of the key are not properly bound.
+
+TPM_RC_SCHEME
+
+inScheme is not compatible with keyHandle; both inScheme and
+key's default scheme are empty; or inScheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from inScheme
+
+TPM_RC_TICKET
+
+validation is not a valid ticket
+
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+the value to sign is larger than allowed for the type of keyHandle
+
+TPM_RC
+TPM2_Sign(
+Sign_In
+Sign_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+TPMT_TK_HASHCHECK
+OBJECT
+
+result;
+ticket;
+*signKey;
+
+)
+{
+
+// Input Validation
+// Get sign key pointer
+signKey = ObjectGet(in->keyHandle);
+// If validation is provided, or the key is restricted, check the ticket
+if(
+in->validation.digest.t.size != 0
+|| signKey->publicArea.objectAttributes.restricted == SET)
+{
+// Compute and compare ticket
+TicketComputeHashCheck(in->validation.hierarchy, &in->digest, &ticket);
+if(!Memory2BEqual(&in->validation.digest.b, &ticket.digest.b))
+return TPM_RC_TICKET + RC_Sign_validation;
+}
+// Command Output
+// pick a scheme for sign. If the input sign scheme is not compatible with
+// the default scheme, return an error.
+result = CryptSelectSignScheme(in->keyHandle, &in->inScheme);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_Sign_keyHandle;
+else
+return RcSafeAddToResult(result, RC_Sign_inScheme);
+}
+// Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or TPM_RC_ATTRIBUTES
+// error may be returned at this point
+result = CryptSign(in->keyHandle, &in->inScheme, &in->digest, &out->signature);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 193
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+
+Trusted Platform Module Library
+
+return result;
+}
+
+Page 194
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+23
+
+Part 3: Commands
+
+Command Audit
+
+23.1
+
+Introduction
+
+If a command has been selected for command audit, the command audit status will be updated when that
+command completes successfully. The digest is updated as:
+
+commandAuditDigestnew ≔ HauditAlg(commandAuditDigestold || cpHash || rpHash)
+
+(5)
+
+where
+
+HauditAlg
+
+hash function using the algorithm of the audit sequence
+
+commandAuditDigest
+
+accumulated digest
+
+cpHash
+
+the command parameter hash
+
+rpHash
+
+the response parameter hash
+
+TPM2_Shutdown() cannot be audited but TPM2_Startup() can be audited. If the cpHash of the
+TPM2_Startup() is TPM_SU_STATE, that would indicate that a TPM2_Shutdown() had been successfully
+executed.
+TPM2_SetCommandCodeAuditStatus() is always audited.
+If the TPM is in Failure mode, command audit is not functional.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 195
+October 31, 2013
+
+ Part 3: Commands
+
+23.2
+
+Trusted Platform Module Library
+
+TPM2_SetCommandCodeAuditStatus
+
+23.2.1 General Description
+This command may be used by the Privacy Administrator or platform to change the audit status of a
+command or to set the hash algorithm used for the audit digest, but not both at the same time.
+If the auditAlg parameter is a supported hash algorithm and not the same as the current algorithm, then
+the TPM will check both setList and clearList are empty (zero length). If so, then the algorithm is changed,
+and the audit digest is cleared. If auditAlg is TPM_ALG_NULL or the same as the current algorithm, then
+the algorithm and audit digest are unchanged and the setList and clearList will be processed.
+NOTE 1
+
+Because the audit digest is cleared, the audit counter will increment the next time that an audited
+command is executed.
+
+Use of TPM2_SetCommandCodeAuditStatus() to change the list of audited commands is an audited
+event. If TPM_CC_SetCommandCodeAuditStatus is in clearList, it is ignored.
+NOTE 2
+
+Use of this command to change the audit hash algorithm is not audited and the digest is reset when
+the command completes. The change in the audit hash algorithm is the evidence that this command
+was used to change the algorithm.
+
+The commands in setList indicate the commands that to be added to the list of audited commands and
+the commands in clearList indicate the commands that will no longer be audited. It is not an error if a
+command in setList is already audited or is not implemented. It is not an error if a command in clearList is
+not currently being audited or is not implemented.
+If a command code is in both setList and clearList, then it will not be audited (that is, setList shall be
+processed first).
+
+Page 196
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+23.2.2 Command and Response
+Table 97 — TPM2_SetCommandCodeAuditStatus Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SetCommandCodeAuditStatus {NV}
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_ENDORSEMENT or
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_ALG_HASH+
+
+auditAlg
+
+hash algorithm for the audit digest; if
+TPM_ALG_NULL, then the hash is not changed
+
+TPML_CC
+
+setList
+
+list of commands that will be added to those that will
+be audited
+
+TPML_CC
+
+clearList
+
+list of commands that will no longer be audited
+
+Table 98 — TPM2_SetCommandCodeAuditStatus Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 197
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+23.2.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+
+#include "InternalRoutines.h"
+#include "SetCommandCodeAuditStatus_fp.h"
+
+TPM_RC
+TPM2_SetCommandCodeAuditStatus(
+SetCommandCodeAuditStatus_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+UINT32
+BOOL
+
+result;
+i;
+changed = FALSE;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+// Update hash algorithm
+if(
+in->auditAlg != TPM_ALG_NULL
+&& in->auditAlg != gp.auditHashAlg)
+{
+// Can't change the algorithm and command list at the same time
+if(in->setList.count != 0 || in->clearList.count != 0)
+return TPM_RC_VALUE + RC_SetCommandCodeAuditStatus_auditAlg;
+// Change the hash algorithm for audit
+gp.auditHashAlg = in->auditAlg;
+// Set the digest size to a unique value that indicates that the digest
+// algorithm has been changed. The size will be cleared to zero in the
+// command audit processing on exit.
+gr.commandAuditDigest.t.size = 1;
+// Save the change of command audit data (this sets g_updateNV so that NV
+// will be updagted on exit.)
+NvWriteReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
+} else {
+// Process set list
+for(i = 0; i < in->setList.count; i++)
+// If change is made in CommandAuditSet, set changed flag
+if(CommandAuditSet(in->setList.commandCodes[i]))
+changed = TRUE;
+// Process clear list
+for(i = 0; i < in->clearList.count; i++)
+// If change is made in CommandAuditClear, set changed flag
+if(CommandAuditClear(in->clearList.commandCodes[i]))
+changed = TRUE;
+// if change was made to command list, update NV
+if(changed)
+// this sets g_updateNV so that NV will be updagted on exit.
+NvWriteReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
+
+Page 198
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+61
+62
+63
+64
+
+Part 3: Commands
+
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 199
+October 31, 2013
+
+ Part 3: Commands
+
+24
+
+Trusted Platform Module Library
+
+Integrity Collection (PCR)
+
+24.1
+
+Introduction
+
+In TPM 1.2, an Event was hashed using SHA-1 and then the 20-octet digest was extended to a PCR
+using TPM_Extend(). This specification allows the use of multiple PCR at a given Index, each using a
+different hash algorithm. Rather than require that the external software generate multiple hashes of the
+Event with each being extended to a different PCR, the Event data may be sent to the TPM for hashing.
+This ensures that the resulting digests will properly reflect the algorithms chosen for the PCR even if the
+calling software is unable to implement the hash algorithm.
+NOTE 1
+
+There is continued support for software hashing of events with TPM2_PCR_Extend().
+
+To support recording of an Event that is larger than the TPM input buffer, the caller may use the
+command sequence described in clause 1.
+Change to a PCR requires authorization. The authorization may be with either an authorization value or
+an authorization policy. The platform-specific specifications determine which PCR may be controlled by
+policy. All other PCR are controlled by authorization.
+If a PCR may be associated with a policy, then the algorithm ID of that policy determines whether the
+policy is to be applied. If the algorithm ID is not TPM_ALG_NULL, then the policy digest associated with
+the PCR must match the policySession→policyDigest in a policy session. If the algorithm ID is
+TPM_ALG_NULL, then no policy is present and the authorization requires an EmptyAuth.
+If a platform-specific specification indicates that PCR are grouped, then all the PCR in the group use the
+same authorization policy or authorization value.
+PcrUpdateCounter counter will be incremented on the successful completion of any command that
+modifies (Extends or resets) a PCR unless the platform-specific specification explicitly excludes the PCR
+from being counted.
+NOTE 2
+
+If a command causes PCR in multiple banks to change, the PCR Update Counter may be
+incremented either once or once for each bank.
+
+A platform-specific specification may designate a set of PCR that are under control of the TCB. These
+PCR may not be modified without the proper authorization. Updates of these PCR shall not cause the
+PCR Update Counter to increment.
+EXAMPLE
+
+Updates of the TCB PCR will not cause the PCR update counter to increment b ecause these PCR
+are changed at the whim of the TCB and are not intended to represent the trust state of the platform.
+
+Page 200
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.2
+
+Part 3: Commands
+
+TPM2_PCR_Extend
+
+24.2.1 General Description
+This command is used to cause an update to the indicated PCR. The digests parameter contains one or
+more tagged digest value identified by an algorithm ID. For each digest, the PCR associated with
+pcrHandle is Extended into the bank identified by the tag (hashAlg).
+EXAMPLE
+
+A SHA1 digest would be Extended into the SHA1 bank and a SHA256 digest would be Extended into
+a SHA256 bank.
+
+For each list entry, the TPM will check to see if pcrNum is implemented for that algorithm. If so, the TPM
+shall perform the following operation:
+
+PCR.digestnew [pcrNum][alg] ≔ Halg(PCR.digestold [pcrNum][alg] || data[alg].buffer))
+
+(6)
+
+where
+
+Halg()
+
+hash function using the hash algorithm associated with the PCR
+instance
+
+PCR.digest
+
+the digest value in a PCR
+
+pcrNum
+
+the PCR numeric
+TPM_RH_PCR0)
+
+alg
+
+the PCR algorithm selector for the digest
+
+data[alg].buffer
+
+the bank-specific data to be extended
+
+selector
+
+(equal
+
+to
+
+pcrHandle
+
+–
+
+If no digest value is specified for a bank, then the PCR in that bank are not modified.
+NOTE 1
+
+This allows consistent operation of the digests list for all of the Event recording commands.
+
+If a digest is present and the PCR in that bank is not implemented, the digest value is not used.
+NOTE 2
+
+If the caller includes digests for algorithms that are not implemented, then the TPM will fail the call
+because the unmarshalling of digests will fail. Each of the entries in the list is a TPMT_HA which is a
+hash algorithm followed by a digest. If the algorithm is not implemented, unmarshalling of the
+hashAlg will fail and the TPM will return TPM_RC_HASH.
+
+If the TPM unmarshals the hashAlg of a list entry and the unmarshaled value is not a hash algorithm
+implemented on the TPM, the TPM shall return TPM_RC_HASH.
+The pcrHandle parameter is allowed to reference TPM_RH_NULL. If so, the input parameters are
+processed but no action is taken by the TPM.
+NOTE 3
+
+This command allows a list of digests so that PCR in all banks may be updated in a single
+command. While the semantics of this command allow multiple extends to a single PCR bank, this is
+not the preferred use and the limit on the number of entries in the list make this use somewhat
+impractical.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 201
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.2.2 Command and Response
+Table 99 — TPM2_PCR_Extend Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Extend {NV}
+
+TPMI_DH_PCR+
+
+@pcrHandle
+
+handle of the PCR
+Auth Handle: 1
+Auth Role: USER
+
+TPML_DIGEST_VALUES
+
+digests
+
+list of tagged digest values to be extended
+
+Table 100 — TPM2_PCR_Extend Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 202
+October 31, 2013
+
+.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_Extend_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+current command locality is not allowed to extend the PCR
+referenced by pcrHandle
+
+TPM_RC
+TPM2_PCR_Extend(
+PCR_Extend_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+UINT32
+
+result;
+i;
+
+// Input Validation
+//
+//
+//
+//
+//
+//
+//
+
+NOTE: This function assumes that the unmarshaling function for 'digests' will
+have validated that all of the indicated hash algorithms are valid. If the
+hash algorithms are correct, the unmarshaling code will unmarshal a digest
+of the size indicated by the hash algorithm. If the overall size is not
+consistent, the unmarshaling code will run out of input data or have input
+data left over. In either case, it will cause an unmarshaling error and this
+function will not be called.
+
+// For NULL handle, do nothing and return success
+if(in->pcrHandle == TPM_RH_NULL)
+return TPM_RC_SUCCESS;
+// Check if the extend operation is allowed by the current command locality
+if(!PCRIsExtendAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// If PCR is state saved and we need to update orderlyState, check NV
+// availability
+if(PCRIsStateSaved(in->pcrHandle) && gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+// Internal Data Update
+// Iterate input digest list to extend
+for(i = 0; i < in->digests.count; i++)
+{
+PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg,
+CryptGetHashDigestSize(in->digests.digests[i].hashAlg),
+(BYTE *) &in->digests.digests[i].digest);
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 203
+October 31, 2013
+
+ Part 3: Commands
+
+24.3
+
+Trusted Platform Module Library
+
+TPM2_PCR_Event
+
+24.3.1 General Description
+This command is used to cause an update to the indicated PCR.
+The data in eventData is hashed using the hash algorithm associated with each bank in which the
+indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
+references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
+TPM2_PCR_Extend().
+A TPM shall support an Event.size of zero through 1,024 inclusive (Event.size is an octet count). An
+Event.size of zero indicates that there is no data but the indicated operations will still occur,
+EXAMPLE 1
+
+If the command implements PCR[2] in a SHA1 bank and a SHA256 bank, then an extend to PCR[2]
+will cause eventData to be hashed twice, once with SHA1 and once with SHA256. The SHA1 hash of
+eventData will be Extended to PCR[2] in the SHA1 bank and the SHA256 hash of eventData will be
+Extended to PCR[2] of the SHA256 bank.
+
+On successful command completion, digests will contain the list of tagged digests of eventData that was
+computed in preparation for extending the data into the PCR. At the option of the TPM, the list may
+contain a digest for each bank, or it may only contain a digest for each bank in which pcrHandle is extant.
+EXAMPLE 2
+
+Assume a TPM that implements a SHA1 bank and a SHA256 bank and that PCR[22] is only
+implemented in the SHA1 bank. If pcrHandle references PCR[22], then digests may contain either a
+SHA1 and a SHA256 digest or just a SHA1 digest.
+
+Page 204
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.3.2 Command and Response
+Table 101 — TPM2_PCR_Event Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Event {NV}
+
+TPMI_DH_PCR+
+
+@pcrHandle
+
+Handle of the PCR
+Auth Handle: 1
+Auth Role: USER
+
+TPM2B_EVENT
+
+eventData
+
+Event data in sized buffer
+
+Table 102 — TPM2_PCR_Event Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPML_DIGEST_VALUES
+
+digests
+
+Family “2.0”
+Level 00 Revision 00.99
+
+.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 205
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_Event_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+current command locality is not allowed to extend the PCR
+referenced by pcrHandle
+
+TPM_RC
+TPM2_PCR_Event(
+PCR_Event_In
+PCR_Event_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+HASH_STATE
+UINT32
+UINT16
+
+result;
+hashState;
+i;
+size;
+
+// Input Validation
+// If a PCR extend is required
+if(in->pcrHandle != TPM_RH_NULL)
+{
+// If the PCR is not allow to extend, return error
+if(!PCRIsExtendAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// If PCR is state saved and we need to update orderlyState, check NV
+// availability
+if(PCRIsStateSaved(in->pcrHandle) && gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+}
+// Internal Data Update
+out->digests.count = HASH_COUNT;
+// Iterate supported PCR bank algorithms to extend
+for(i = 0; i < HASH_COUNT; i++)
+{
+TPM_ALG_ID hash = CryptGetHashAlgByIndex(i);
+out->digests.digests[i].hashAlg = hash;
+size = CryptStartHash(hash, &hashState);
+CryptUpdateDigest2B(&hashState, &in->eventData.b);
+CryptCompleteHash(&hashState, size,
+(BYTE *) &out->digests.digests[i].digest);
+if(in->pcrHandle != TPM_RH_NULL)
+PCRExtend(in->pcrHandle, hash, size,
+(BYTE *) &out->digests.digests[i].digest);
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 206
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.4
+
+Part 3: Commands
+
+TPM2_PCR_Read
+
+24.4.1 General Description
+This command returns the values of all PCR specified in pcrSelect.
+The TPM will process the list of TPMS_PCR_SELECTION in pcrSelectionIn in order. Within each
+TPMS_PCR_SELECTION, the TPM will process the bits in the pcrSelect array in ascending PCR order
+(see Part 2 for definition of the PCR order). If a bit is SET, and the indicated PCR is present, then the
+TPM will add the digest of the PCR to the list of values to be returned in pcrValue.
+The TPM will continue processing bits until all have been processed or until pcrValues would be too large
+to fit into the output buffer if additional values were added.
+The returned pcrSelectionOut will have a bit SET in its pcrSelect structures for each value present in
+pcrValues.
+The current value of the PCR Update Counter is returned in pcrUpdateCounter.
+The returned list may be empty if none of the selected PCR are implemented.
+NOTE
+
+If no PCR are returned from a bank, the selector for the bank will be present in pcrSelectionOut.
+
+No authorization is required to read a PCR and any implemented PCR may be read from any locality.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 207
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.4.2 Command and Response
+Table 103 — TPM2_PCR_Read Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Read
+
+TPML_PCR_SELECTION
+
+pcrSelectionIn
+
+The selection of PCR to read
+
+Table 104 — TPM2_PCR_Read Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+UINT32
+
+pcrUpdateCounter
+
+the current value of the PCR update counter
+
+TPML_PCR_SELECTION
+
+pcrSelectionOut
+
+the PCR in the returned list
+
+TPML_DIGEST
+
+pcrValues
+
+the contents of the PCR indicated in pcrSelect as
+tagged digests
+
+Page 208
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.4.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
+#include "InternalRoutines.h"
+#include "PCR_Read_fp.h"
+
+TPM_RC
+TPM2_PCR_Read(
+PCR_Read_In
+PCR_Read_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Call PCR read function. input pcrSelectionIn parameter could be changed
+// to reflect the actual PCR being returned
+PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter);
+out->pcrSelectionOut = in->pcrSelectionIn;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 209
+October 31, 2013
+
+ Part 3: Commands
+
+24.5
+
+Trusted Platform Module Library
+
+TPM2_PCR_Allocate
+
+24.5.1 General Description
+This command is used to set the desired PCR allocation of PCR and algorithms. This command requires
+platformAuth.
+The TPM will evaluate the request and, if sufficient memory is available for the requested allocation, the
+TPM will store the allocation request for use during the next TPM2_Startup(TPM_SU_CLEAR) operation.
+The PCR allocation in place when this command is executed will be retained until the next
+TPM2_Startup(TPM_SU_CLEAR).
+If no allocation is specified for a bank, then no PCR will be allocated to that bank. If a bank is listed more
+than once, then the last selection in the pcrAllocation list is the one that the TPM will attempt to allocate.
+This command shall not allocate more PCR in any bank than there are PCR attribute definitions. The
+PCR attribute definitions indicate how a PCR is to be managed – if it is resettable, the locality for update,
+etc. In the response to this command, the TPM returns the maximum number of PCR allowed for any
+bank.
+If the command is properly authorized, it will return SUCCESS even though the request fails. This is to
+allow the TPM to return information about the size needed for the requested allocation and the size
+available. If the sizeNeeded parameter in the return is less than or equal to the sizeAvailable parameter,
+then the allocationSuccess parameter will be YES.
+After this command, TPM2_Shutdown() is only allowed to have a startupType equal to TPM_SU_CLEAR.
+NOTE
+
+Even if this command does not cause the PCR allocation to change, the TPM cannot have its state
+saved. This is done in order to simplify the implementation. There is no need to optimize this
+command as it is not expected to be used more than once in the lifetime of the TPM (it can be used
+any number of times but there is no justification for optimization) .
+
+Page 210
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.5.2 Command and Response
+Table 105 — TPM2_PCR_Allocate Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Allocate {NV}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPML_PCR_SELECTION
+
+pcrAllocation
+
+the requested allocation
+
+Table 106 — TPM2_PCR_Allocate Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_YES_NO
+
+allocationSuccess
+
+YES if the allocation succeeded
+
+UINT32
+
+maxPCR
+
+maximum number of PCR that may be in a bank
+
+UINT32
+
+sizeNeeded
+
+number of octets required to satisfy the request
+
+UINT32
+
+sizeAvailable
+
+Number of octets available. Computed before the
+allocation.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 211
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.5.3 Detailed Actions
+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
+33
+34
+
+#include "InternalRoutines.h"
+#include "PCR_Allocate_fp.h"
+
+TPM_RC
+TPM2_PCR_Allocate(
+PCR_Allocate_In
+PCR_Allocate_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point.
+// Note: These codes are not listed in the return values above because it is
+// an implementation choice to check in this routine rather than in a common
+// function that is called before these actions are called. These return values
+// are described in the Response Code section of Part 3.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Command Output
+// Call PCR Allocation function.
+out->allocationSuccess = PCRAllocate(&in->pcrAllocation, &out->maxPCR,
+&out->sizeNeeded, &out->sizeAvailable);
+// if re-configuration succeeds, set the flag to indicate PCR configuration is
+// going to be changed in next boot
+if(out->allocationSuccess == YES)
+g_pcrReConfig = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 212
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.6
+
+Part 3: Commands
+
+TPM2_PCR_SetAuthPolicy
+
+24.6.1 General Description
+This command is used to associate a policy with a PCR or group of PCR. The policy determines the
+conditions under which a PCR may be extended or reset.
+A policy may only be associated with a PCR that has been defined by a platform-specific specification as
+allowing a policy. If the TPM implementation does not allow a policy for pcrNum, the TPM shall return
+TPM_RC_VALUE.
+A platform-specific specification may group PCR so that they share a common policy. In such case, a
+pcrNum that selects any of the PCR in the group will change the policy for all PCR in the group.
+The policy setting is persistent and may only be changed by TPM2_PCR_SetAuthPolicy() or by
+TPM2_ChangePPS().
+Before this command is first executed on a TPM or after TPM2_ChangePPS(), the access control on the
+PCR will be set to the default value defined in the platform-specific specification.
+NOTE 1
+
+It is expected that the typical default will be with the policy hash set to TPM_ALG_NULL and an
+Empty Buffer for the authPolicy value. This will allow an EmptyAuth to be used as the authorization
+value.
+
+If the size of the data buffer in authPolicy is not the size of a digest produced by hashAlg, the TPM shall
+return TPM_RC_SIZE.
+NOTE 2
+
+If hashAlg is TPM_ALG_NULL, then the size is required to be zero.
+
+This command requires platformAuth/platformPolicy.
+NOTE 3
+
+If the PCR is in multiple policy sets, the policy will be changed in only one set. The set that is
+changed will be implementation dependent.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 213
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.6.2 Command and Response
+Table 107 — TPM2_PCR_SetAuthPolicy Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_SetAuthPolicy {NV}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+authPolicy
+
+the desired authPolicy
+
+TPMI_ALG_HASH+
+
+policyDigest
+
+the digest of the policy
+
+TPMI_DH_PCR
+
+pcrNum
+
+the PCR for which the policy is to be set
+
+Table 108 — TPM2_PCR_SetAuthPolicy Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 214
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.6.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_SetAuthPolicy_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+size of authPolicy is not the size of a digest produced by policyDigest
+
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+
+Meaning
+
+PCR referenced by pcrNum is not a member of a PCR policy group
+
+TPM_RC
+TPM2_PCR_SetAuthPolicy(
+PCR_SetAuthPolicy_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+
+groupIndex;
+
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation:
+// Check the authPolicy consistent with hash algorithm
+if(in->authPolicy.t.size != CryptGetHashDigestSize(in->policyDigest))
+return TPM_RC_SIZE + RC_PCR_SetAuthPolicy_authPolicy;
+// If PCR does not belong to a policy group, return TPM_RC_VALUE
+if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex))
+return TPM_RC_VALUE + RC_PCR_SetAuthPolicy_pcrNum;
+// Internal Data Update
+// Set PCR policy
+gp.pcrPolicies.hashAlg[groupIndex] = in->policyDigest;
+gp.pcrPolicies.policy[groupIndex] = in->authPolicy;
+// Save new policy to NV
+NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 215
+October 31, 2013
+
+ Part 3: Commands
+
+24.7
+
+Trusted Platform Module Library
+
+TPM2_PCR_SetAuthValue
+
+24.7.1 General Description
+This command changes the authValue of a PCR or group of PCR.
+An authValue may only be associated with a PCR that has been defined by a platform-specific
+specification as allowing an authorization value. If the TPM implementation does not allow an
+authorization for pcrNum, the TPM shall return TPM_RC_VALUE. A platform-specific specification may
+group PCR so that they share a common authorization value. In such case, a pcrNum that selects any of
+the PCR in the group will change the authValue value for all PCR in the group.
+The authorization setting is set to EmptyAuth on each STARTUP(CLEAR) or by TPM2_Clear(). The
+authorization setting is preserved by SHUTDOWN(STATE).
+
+Page 216
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.7.2 Command and Response
+Table 109 — TPM2_PCR_SetAuthValue Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_SetAuthValue
+
+TPMI_DH_PCR
+
+@pcrHandle
+
+handle for a PCR that may have an authorization value
+set
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+auth
+
+the desired authorization value
+
+Table 110 — TPM2_PCR_SetAuthValue Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 217
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_SetAuthValue_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+
+Meaning
+PCR referenced by pcrHandle is not a member of a PCR
+authorization group
+
+TPM_RC
+TPM2_PCR_SetAuthValue(
+PCR_SetAuthValue_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+TPM_RC
+
+groupIndex;
+result;
+
+// Input Validation:
+// If PCR does not belong to an auth group, return TPM_RC_VALUE
+if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex))
+return TPM_RC_VALUE;
+// The command may cause the orderlyState to be cleared due to the update of
+// state clear data. If this is the case, Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+// Internal Data Update
+// Set PCR authValue
+gc.pcrAuthValues.auth[groupIndex] = in->auth;
+return TPM_RC_SUCCESS;
+}
+
+Page 218
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.8
+
+Part 3: Commands
+
+TPM2_PCR_Reset
+
+24.8.1 General Description
+If the attribute of a PCR allows the PCR to be reset and proper authorization is provided, then this
+command may be used to set the PCR to zero. The attributes of the PCR may restrict the locality that can
+perform the reset operation.
+NOTE 1
+
+The definition of TPMI_DH_PCR in Part 2 indicates that if pcrHandle is out of the allowed range for
+PCR, then the appropriate return value is TPM_RC_VALUE.
+
+If pcrHandle references a PCR that cannot be reset, the TPM shall return TPM_RC_LOCALITY.
+NOTE 2
+
+TPM_RC_LOCALITY is returned because the reset attributes are defined on a per -locality basis.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 219
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.8.2 Command and Response
+Table 111 — TPM2_PCR_Reset Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Reset {NV}
+
+TPMI_DH_PCR
+
+@pcrHandle
+
+the PCR to reset
+Auth Index: 1
+Auth Role: USER
+
+Table 112 — TPM2_PCR_Reset Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 220
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.8.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_Reset_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+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
+33
+34
+35
+36
+
+Meaning
+current command locality is not allowed to reset the PCR referenced
+by pcrHandle
+
+TPM_RC
+TPM2_PCR_Reset(
+PCR_Reset_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input Validation
+// Check if the reset operation is allowed by the current command locality
+if(!PCRIsResetAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// If PCR is state saved and we need to update orderlyState, check NV
+// availability
+if(PCRIsStateSaved(in->pcrHandle) && gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+g_clearOrderly = TRUE;
+}
+// Internal Data Update
+// Reset seleccted PCR in all banks to 0
+PCRSetValue(in->pcrHandle, 0);
+// Indicate that the PCR changed so that pcrCounter will be incremented if
+// necessary.
+PCRChanged(in->pcrHandle);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 221
+October 31, 2013
+
+ Part 3: Commands
+
+24.9
+
+Trusted Platform Module Library
+
+_TPM_Hash_Start
+
+24.9.1 Description
+This indication from the TPM interface indicates the start of a dynamic Core Root of Trust for
+Measurement (D-CRTM) measurement sequence. On receipt of this indication, the TPM will initialize an
+Event sequence context.
+If no object memory is available for creation of the sequence context, the TPM will flush the context of an
+object so that creation of the Event sequence context will always succeed.
+A platform-specific specification may allow this indication before TPM2_Startup().
+NOTE
+
+If this indication occurs after TPM2_Startup(), it is the responsibility of software to ensure that an
+object context slot is available or to deal with the consequences of having the TPM select an
+arbitrary object to be flushed. If this indication occurs before TPM2_Startup() then all context slots
+are available.
+
+Page 222
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.9.2 Detailed Actions
+1
+
+#include "InternalRoutines.h"
+
+This function is called to process a _TPM_Hash_Start() indication.
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+void
+_TPM_Hash_Start(void)
+{
+TPM_RC
+TPMI_DH_OBJECT
+
+result;
+handle;
+
+// If a DRTM sequence object exists, terminate it.
+if(g_DRTMHandle != TPM_RH_UNASSIGNED)
+ObjectTerminateEvent();
+// Create an event sequence object and store the handle in global
+// g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point
+// The null value for the 'auth' parameter will cause the sequence structure to
+// be allocated without being set as present. This keeps the sequence from
+// being left behind if the sequence is terminated early.
+result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
+// If a free slot was not available, then free up a slot.
+if(result != TPM_RC_SUCCESS)
+{
+// An implementation does not need to have a fixed relationship between
+// slot numbers and handle numbers. To handle the general case, scan for
+// a handle that is assigned an free it for the DRTM sequence.
+// In the reference implementation, the relationship between handles and
+// slots is fixed. So, if the call to ObjectCreateEvenSequence()
+// failed indicating that all slots are occupied, then the first handle we
+// are going to check (TRANSIENT_FIRST) will be occupied. It will be freed
+// so that it can be assigned for use as the DRTM sequence object.
+for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++)
+{
+// try to flush the first object
+if(ObjectIsPresent(handle))
+break;
+}
+// If the first call to find a slot fails but none of the slots is occupied
+// then there's a big problem
+pAssert(handle < TRANSIENT_LAST);
+// Free the slot
+ObjectFlush(handle);
+// Try to create an event sequence object again. This time, we must
+// succeed.
+result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
+pAssert(result == TPM_RC_SUCCESS);
+}
+return;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 223
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.10 _TPM_Hash_Data
+24.10.1
+
+Description
+
+This indication from the TPM interface indicates arrival of one or more octets of data that are to be
+included in the Core Root of Trust for Measurement (CRTM) sequence context created by the
+_TPM_Hash_Start indication. The context holds data for each hash algorithm for each PCR bank
+implemented on the TPM.
+If no DRTM Event Sequence context exists, this indication is discarded and no other action is performed.
+
+Page 224
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.10.2
+1
+2
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "Platform.h"
+
+This function is called to process a _TPM_Hash_Data() indication.
+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
+
+void
+_TPM_Hash_Data(
+UINT32
+BYTE
+
+dataSize,
+*data
+
+UINT32
+HASH_OBJECT
+
+// IN: size of data to be extend
+// IN: data buffer
+
+i;
+*hashObject;
+
+)
+{
+
+// If there is no DRTM sequence object, then _TPM_Hash_Start
+// was not called so this function returns without doing
+// anything.
+if(g_DRTMHandle == TPM_RH_UNASSIGNED)
+return;
+hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
+pAssert(hashObject->attributes.eventSeq);
+// For each of the implemented hash algorithms, update the digest with the
+// data provided. NOTE: the implementation could be done such that the TPM
+// only computes the hash for the banks that contain the DRTM PCR.
+for(i = 0; i < HASH_COUNT; i++)
+{
+// Update sequence object
+CryptUpdateDigest(&hashObject->state.hashState[i], dataSize, data);
+}
+return;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 225
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.11 _TPM_Hash_End
+24.11.1
+
+Description
+
+This indication from the TPM interface indicates the end of the CRTM measurement. This indication is
+discarded and no other action performed if the TPM does not contain a CRTM Event sequence context.
+NOTE
+
+A CRTM Event Sequence context is created by _TPM_Hash_Start().
+
+If the CRTM Event sequence occurs after TPM2_Startup(), the TPM will set all of the PCR designated in
+the platform-specific specifications as resettable by this event to the value indicated in the platform
+specific specification, and increment restartCount. The TPM will then Extend the Event Sequence
+digest/digests into the designated, DRTM PCR.
+PCR[DRTM][hashAlg] ≔ HhashAlg (initial_value || HhashAlg (hash_data))
+
+(7)
+
+where
+DRTM
+
+index for CRTM PCR designated by a platform-specific
+specification
+
+hashAlg
+
+hash algorithm associated with a bank of PCR
+
+initial_value
+
+initialization value specified in the platform-specific specification
+(should be 0…0)
+
+hash_data
+
+all the octets of data received in _TPM_Hash_Data indications
+
+A _TPM_Hash_End indication that occurs after TPM2_Startup() will increment pcrUpdateCounter unless
+a platform-specific specification excludes modifications of PCR[DRTM] from causing an increment.
+A platform-specific specification may allow an H-CRTM Event Sequence before TPM2_Startup(). If so,
+_TPM_Hash_End will complete the digest, initialize PCR[0] with a digest-size value of 4, and then extend
+the H-CRTM Event Sequence data into PCR[0].
+PCR[0][hashAlg] ≔ HhashAlg (0…04 || HhashAlg (hash_data))
+NOTE
+
+(8)
+
+The entire sequence of _TPM_Hash_Start, _TPM_Hash_Data, and _TPM_Hash_End are required to
+complete before TPM2_Startup() or the sequence will have no effect on the TPM.
+
+Page 226
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.11.2
+1
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+
+This function is called to process a _TPM_Hash_End() indication.
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+
+void
+_TPM_Hash_End(void)
+{
+UINT32
+TPM2B_DIGEST
+HASH_OBJECT
+TPMI_DH_PCR
+
+i;
+digest;
+*hashObject;
+pcrHandle;
+
+// If the DRTM handle is not being used, then either _TPM_Hash_Start has not
+// been called, _TPM_Hash_End was previously called, or some other command
+// was executed and the sequence was aborted.
+if(g_DRTMHandle == TPM_RH_UNASSIGNED)
+return;
+// Get DRTM sequence object
+hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
+// Is this _TPM_Hash_End after Startup or before
+if(TPMIsStarted())
+{
+// After
+// Reset the DRTM PCR
+PCRResetDynamics();
+// Extend the DRTM_PCR.
+pcrHandle = PCR_FIRST + DRTM_PCR;
+// DRTM sequence increments restartCount
+gr.restartCount++;
+}
+else
+{
+pcrHandle = PCR_FIRST + HCRTM_PCR;
+}
+// Complete hash and extend PCR, or if this is an HCRTM, complete
+// the hash and write the PCR
+for(i = 0; i < HASH_COUNT; i++)
+{
+TPMI_ALG_HASH
+hash = CryptGetHashAlgByIndex(i);
+// Complete hash
+digest.t.size = CryptGetHashDigestSize(hash);
+CryptCompleteHash2B(&hashObject->state.hashState[i], &digest.b);
+// If this is DRTM, extend to zeroed PCR
+// If this is H-DRTM, copy to HCRM PCR
+if(TPMIsStarted())
+// Extend PCR
+PCRExtend(pcrHandle, hash, digest.t.size, digest.t.buffer);
+else
+PcrWrite(pcrHandle, hash, &digest);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 227
+October 31, 2013
+
+ Part 3: Commands
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+
+Trusted Platform Module Library
+
+}
+// Flush sequence object.
+ObjectFlush(g_DRTMHandle);
+g_DRTMHandle = TPM_RH_UNASSIGNED;
+g_DrtmPreStartup = TRUE;
+return;
+}
+
+Page 228
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25
+
+Part 3: Commands
+
+Enhanced Authorization (EA) Commands
+
+25.1
+
+Introduction
+
+The commands in this clause 1 are used for policy evaluation. When successful, each command will
+update the policySession→policyDigest in a policy session context in order to establish that the
+authorizations required to use an object have been provided. Many of the commands will also modify
+other parts of a policy context so that the caller may constrain the scope of the authorization that is
+provided.
+NOTE 1
+
+Many of the terms used in this clause are described in detail i n Part 1 and are not redefined in this
+clause.
+
+The policySession parameter of the command is the handle of the policy session context to be modified
+by the command.
+If the policySession parameter indicates a trial policy session, then the policySession→policyDigest will
+be updated and the indicated validations are not performed.
+NOTE 2
+
+A policy session is a trial policy by TPM2_StartAuthSession( sessionType = TPM_SE_TRIAL).
+
+NOTE 3
+
+Unless there is an unmarshaling error in the parameters of the command, these commands will
+return TPM_RC_SUCCESS when policySession references a trial session.
+
+NOTE 4
+
+Policy context other than the policySession→policyDigest may be updated for a trial policy but it is
+not required.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 229
+October 31, 2013
+
+ Part 3: Commands
+
+25.2
+
+Trusted Platform Module Library
+
+Signed Authorization Actions
+
+25.2.1 Introduction
+The TPM2_PolicySigned, TPM_PolicySecret, and TPM2_PolicyTicket commands use many of the same
+functions. This clause consolidates those functions to simplify the document and to ensure uniformity of
+the operations.
+25.2.2 Policy Parameter Checks
+These parameter checks will be performed when indicated in the description of each of the commands:
+a) nonceTPM – If this parameter is not the Empty Buffer, and
+policySession→nonceTPM, then the TPM shall return TPM_RC_VALUE.
+
+it
+
+does
+
+not
+
+match
+
+b) expiration – If this parameter is not zero, then its absolute value is compared to the time in seconds
+since the policySession→nonceTPM was generated. If more time has passed than indicted in
+expiration, the TPM shall return TPM_RC_EXPIRED. If nonceTPM is the Empty buffer, and expiration
+is non-zero, then the TPM shall return TPM_RC_EXPIRED.
+c) timeout – This parameter is compared to the current TPM time. If policySession→timeout is in the
+past, then the TPM shall return TPM_RC_EXPIRED.
+NOTE 1
+
+The expiration parameter is present in the TPM2_PolicySigned and TPM2_PolicySecret
+command and timeout is the analogous parameter in the TPM2_PolicyTicket command.
+
+d) cpHashA – If this parameter is not an Empty Buffer
+NOTE 2
+
+CpHashA is the hash of the command to be executed using this policy session in the
+authorization. The algorithm used to compute this hash is required to be the algorithm of the
+policy session.
+
+1) the TPM shall return TPM_RC_CPHASH if policySession→cpHash does not have its default
+value or the contents of policySession→cpHash are not the same as cpHashA; or
+NOTE 3
+
+CpHash is the expected cpHash value held in the policy session context.
+
+2) the TPM shall return TPM_RC_SIZE
+policySession→policyDigest.
+NOTE 4
+
+Page 230
+October 31, 2013
+
+if
+
+cpHashA
+
+is
+
+not
+
+the
+
+same
+
+size
+
+as
+
+PolicySession→policyDigest is the size of the digest produced by the hash algorithm used to
+compute policyDigest.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.2.3 PolicyDigest Update Function (PolicyUpdate())
+This is the update process for policySession→policyDigest used by TPM2_PolicySigned(),
+TPM2_PolicySecret(), TPM2_PolicyTicket(), and TPM2_PolicyAuthorize(). The function prototype for the
+update function is:
+
+PolicyUpdate(commandCode, arg2, arg3)
+
+(9)
+
+where
+
+arg2
+
+a TPM2B_NAME
+
+arg3
+
+a TPM2B
+
+These parameters are used to update policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || commandCode || arg2.name)
+
+(10)
+
+policyDigestnew+1 ≔ HpolicyAlg(policyDigestnew || arg3.buffer)
+
+(11)
+
+followed by
+
+where
+
+HpolicyAlg()
+
+the hash algorithm chosen when the policy session was started
+
+NOTE 1
+
+If arg3 is a TPM2B_NAME, then arg3.buffer will actually be an arg3.name.
+
+NOTE 2
+
+The arg2.size and arg3.size fields are not included in the hashes.
+
+NOTE 3
+
+PolicyUpdate() uses two hashes because arg2 and arg3 are variable-sized and the concatenation of
+arg2 and arg3 in a single hash could produce the same digest even though arg2 and arg3 are
+different. Processing of the arguments separately in different Extend operation insures that the
+digest produced by PolicyUpdate() will be different if arg2 and arg3 are different.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 231
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.2.4 Policy Context Updates
+When a policy command modifies some part of the policy session context other than the
+policySession→policyDigest, the following rules apply.
+
+
+cpHash – this parameter may only be changed if it contains its initialization value (an Empty String).
+If cpHash is not the Empty String when a policy command attempts to update it, the TPM will return
+an error (TPM_RC_CPHASH) if the current and update values are not the same.
+
+
+
+timeOut – this parameter may only be changed to a smaller value. If a command attempts to update
+this value with a larger value (longer into the future), the TPM will discard the update value. This is
+not an error condition.
+
+
+
+commandCode – once set by a policy command, this value may not be change except by
+TPM2_PolicyRestart(). If a policy command tries to change this to a different value, an error is
+returned (TPM_RC_POLICY_CC).
+
+
+
+pcrUpdateCounter – this parameter is updated by TPM2_PolicyPCR(). This value may only be set
+once during a policy. Each time TPM2_PolicyPCR() executes, it checks to see if
+policySession→pcrUpdateCounter has its default state indicating that this is the first
+TPM2_PolicyPCR(). If it has its default value, then policySession→pcrUpdateCounter is set to the
+current value of pcrUpdateCounter. If policySession→pcrUpdateCounter does not have its default
+value and its value is not the same as pcrUpdateCounter, the TPM shall return
+TPM_RC_PCR_CHANGED.
+NOTE
+
+If this parameter and pcrUpdateCounter are not the same, it indicates that PCR have changed
+since checked by the previous TPM2_PolicyPCR(). Since they have changed, the previous PCR
+validation is no longer valid.
+
+
+
+commandLocality – this parameter is the logical AND of all enabled localities. All localities are
+enabled for a policy when the policy session is created. TPM2_PolicyLocalities() selectively disables
+localities. Once use of a policy for a locality has been disabled, it cannot be enabled except by
+TPM2_PolicyRestart().
+
+
+
+isPPRequired – once SET, this parameter may only be CLEARed by TPM2_PolicyRestart().
+
+
+
+isAuthValueNeeded – once SET, this parameter may only be CLEARed by TPM2_PolicyPassword()
+or TPM2_PolicyRestart().
+
+
+
+isPasswordNeeded – once SET, this parameter may only be CLEARed by TPM2_PolicyAuthValue()
+or TPM2_PolicyRestart(),
+
+NOTE
+
+Both TPM2_PolicyAuthValue() and TPM2_PolicyPassword() change policySession→policyDigest in
+the same way. The different commands simply indicate to the TPM the format used for the authValue
+(HMAC or clear text). Both commands could be in the same policy. The final instance of these
+commands determines the format.
+
+Page 232
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.2.5 Policy Ticket Creation
+If for TPM2_PolicySigned() or TPM2_PolicySecret() the caller specified a negative value for expiration,
+and the policy update succeeds, then the TPM will return a ticket that includes a value indicating when
+the authorization expires. The required computation for the digest in the authorization ticket is:
+
+HMAC(proof, HpolicyAlg(ticketType || timeout || cpHashA || policyRef || authObject→Name)) (12)
+where
+
+proof
+
+secret associated with the storage primary seed (SPS) of the
+TPM
+
+HpolicyAlg
+
+hash function using the hash algorithm associated with the policy
+session
+
+ticketType
+
+either TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED,
+used to indicate type of the ticket
+
+NOTE 1
+
+If
+the
+ticket
+is
+produced
+by
+TPM2_PolicySecret()
+then
+ticketType
+is
+TPM_ST_AUTH_SECRET and if produced by TPM2_PolicySigned() then ticketType is
+TPM_ST_AUTH_SIGNED.
+
+timeout
+
+NOTE 2
+
+implementation-specific representation of the expiration time of
+the ticket; required to be the implementation equivalent of
+policySession→startTime plus the absolute value of expiration
+Timeout is not the same as expiration. The expiration value in the aHash is a relative time,
+using the creation time of the authorization session (TPM2_StartAuthSession()) as its
+reference. The timeout parameter is an absolute time, using TPM Clock as the reference.
+
+cpHashA
+
+the command parameter digest for the command being
+authorized; computed using the hash algorithm of the policy
+session
+
+policyRef
+
+the commands that use this function have a policyRef parameter
+and the value of that parameter is used here
+
+authObject→Name
+
+Name associated with the authObject parameter
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 233
+October 31, 2013
+
+ Part 3: Commands
+25.3
+
+Trusted Platform Module Library
+
+TPM2_PolicySigned
+
+25.3.1 General Description
+This command includes a signed authorization in a policy. The command ties the policy to a signing key
+by including the Name of the signing key in the policyDigest
+If policySession is a trial session, the TPM will not check the signature and will update
+policySession→policyDigest as described in 25.2.3 as if a properly signed authorization was received; but
+no ticket will be produced.
+If policySession is not a trial session, the TPM will validate auth and only perform the update if it is a valid
+signature over the fields of the command.
+The authorizing object will sign a digest of the authorization qualifiers: nonceTPM, expiration, cpHashA,
+and policyRef. The digest is computed as:
+
+aHash ≔ HauthAlg(nonceTPM || expiration || cpHashA || policyRef)
+
+(13)
+
+where
+
+HauthAlg()
+NOTE 1
+
+the hash associated with the auth parameter of this command
+Each signature and key combination indicates the scheme and each scheme has an
+associated hash.
+
+nonceTPM
+
+the nonceTPM parameter from the TPM2_StartAuthSession()
+response. If the authorization is not limited to this session, the
+size of this value is zero.
+
+expiration
+
+time limit on authorization set by authorizing object. This 32-bit
+value is set to zero if the expiration time is not being set.
+
+cpHashA
+
+digest of the command parameters for the command being
+approved using the hash algorithm of the policy session. Set to
+an EmptyAuth if the authorization is not limited to a specific
+command.
+
+NOTE 2
+
+This is not the cpHash of this TPM2_PolicySigned() command.
+
+policyRef
+EXAMPLE
+
+an opaque value determined by the authorizing entity. Set to the
+Empty Buffer if no value is present.
+
+The computation for an aHash if there are no restrictions is:
+
+aHash ≔ HauthAlg(00 00 00 0016)
+which is the hash of an expiration time of zero.
+
+The aHash is signed by the private key associated with key. The signature and signing parameters are
+combined to create the auth parameter.
+The TPM will perform the parameter checks listed in 25.2.2
+If the parameter checks succeed, the TPM will construct a test digest (tHash) over the provided
+parameters using the same formulation a shown in equation (13) above.
+If tHash does not match the digest of the signed aHash, then the authorization fails and the TPM shall
+return TPM_RC_POLICY_FAIL and make no change to policySession→policyDigest.
+
+Page 234
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+When all validations have succeeded, policySession→policyDigest is updated by PolicyUpdate() (see
+25.2.3).
+
+PolicyUpdate(TPM_CC_PolicySigned, authObject→Name, policyRef)
+
+(14)
+
+If the cpHashA parameter is not an Empty Buffer, it is copied to policySession→cpHash.
+The TPM will optionally produce a ticket as described in 25.2.5.
+Authorization to use authObject is not required.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 235
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.3.2 Command and Response
+Table 113 — TPM2_PolicySigned Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicySigned
+
+TPMI_DH_OBJECT
+
+authObject
+
+handle for a public key that will validate the signature
+Auth Index: None
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_NONCE
+
+nonceTPM
+
+the policy nonce for the session
+If the nonce is not included in the authorization
+qualification, this field is the Empty Buffer.
+
+cpHashA
+
+digest of the command parameters to which this
+authorization is limited
+This is not the cpHash for this command but the cpHash
+for the command to which this policy session will be
+applied. If it is not limited, the parameter will be the
+Empty Buffer.
+
+TPM2B_NONCE
+
+policyRef
+
+a reference to a policy relating to the authorization –
+may be the Empty Buffer
+Size is limited to be no larger than the nonce size
+supported on the TPM.
+
+INT32
+
+expiration
+
+time when authorization will expire, measured in
+seconds from the time that nonceTPM was generated
+If expiration is zero, a NULL Ticket is returned.
+
+TPMT_SIGNATURE
+
+auth
+
+signed authorization (not optional)
+
+TPM2B_DIGEST
+
+Description
+
+Table 114 — TPM2_PolicySigned Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_TIMEOUT
+
+timeout
+
+TPMT_TK_AUTH
+
+policyTicket
+
+Page 236
+October 31, 2013
+
+implementation-specific time value, used to indicate to
+the TPM when the ticket expires
+NOTE
+
+If policyTicket is a NULL Ticket, then this shall be
+the Empty Buffer.
+
+produced if the command succeeds and expiration in
+the command was non-zero; this ticket will use the
+TPMT_ST_AUTH_SIGNED structure tag
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Policy_spt_fp.h"
+#include "PolicySigned_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+cpHash was previously set to a different value
+
+TPM_RC_EXPIRED
+
+expiration indicates a time in the past or expiration is non-zero but no
+nonceTPM is present
+
+TPM_RC_HANDLE
+
+authObject need to have sensitive portion loaded
+
+TPM_RC_KEY
+
+authObject is not a signing scheme
+
+TPM_RC_NONCE
+
+nonceTPM is not the nonce associated with the policySession
+
+TPM_RC_SCHEME
+
+the signing scheme of auth is not supported by the TPM
+
+TPM_RC_SIGNATURE
+
+the signature is not genuine
+
+TPM_RC_SIZE
+
+input cpHash has wrong size
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+
+Meaning
+
+input policyID or expiration does not match the internal data in policy
+session
+
+TPM_RC
+TPM2_PolicySigned(
+PolicySigned_In
+PolicySigned_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+SESSION
+OBJECT
+TPM2B_NAME
+TPM2B_DIGEST
+HASH_STATE
+UINT32
+
+result = TPM_RC_SUCCESS;
+*session;
+*authObject;
+entityName;
+authHash;
+hashState;
+expiration = (in->expiration < 0)
+? -(in->expiration) : in->expiration;
+authTimeout = 0;
+
+)
+{
+
+UINT64
+// Input Validation
+
+// Set up local pointers
+session = SessionGet(in->policySession);
+authObject = ObjectGet(in->authObject);
+
+// the session structure
+// pointer for the object
+//
+providing authorization
+//
+signature
+
+// Only do input validation if this is not a trial policy session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+if(expiration != 0)
+authTimeout = expiration * 1000 + session->startTime;
+result = PolicyParameterChecks(session, authTimeout,
+&in->cpHashA, &in->nonceTPM,
+RC_PolicySigned_nonceTPM,
+RC_PolicySigned_cpHashA,
+RC_PolicySigned_expiration);
+if(result != TPM_RC_SUCCESS)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 237
+October 31, 2013
+
+ Part 3: Commands
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
+Trusted Platform Module Library
+
+return result;
+// Re-compute the digest being signed
+/*(See part 3 specification)
+// The digest is computed as:
+//
+aHash := hash ( nonceTPM | expiration | cpHashA | policyRef)
+// where:
+//
+hash()
+the hash associated with the signed auth
+//
+nonceTPM
+the nonceTPM value from the TPM2_StartAuthSession .
+//
+response If the authorization is not limited to this
+//
+session, the size of this value is zero.
+//
+expiration time limit on authorization set by authorizing object.
+//
+This 32-bit value is set to zero if the expiration
+//
+time is not being set.
+//
+cpHashA
+hash of the command parameters for the command being
+//
+approved using the hash algorithm of the PSAP session.
+//
+Set to NULLauth if the authorization is not limited
+//
+to a specific command.
+//
+policyRef
+hash of an opaque value determined by the authorizing
+//
+object. Set to the NULLdigest if no hash is present.
+*/
+// Start hash
+authHash.t.size = CryptStartHash(CryptGetSignHashAlg(&in->auth),
+&hashState);
+// add nonceTPM
+CryptUpdateDigest2B(&hashState, &in->nonceTPM.b);
+// add expiration
+CryptUpdateDigestInt(&hashState, sizeof(UINT32), (BYTE*) &in->expiration);
+// add cpHashA
+CryptUpdateDigest2B(&hashState, &in->cpHashA.b);
+// add policyRef
+CryptUpdateDigest2B(&hashState, &in->policyRef.b);
+// Complete digest
+CryptCompleteHash2B(&hashState, &authHash.b);
+// Validate Signature. A TPM_RC_SCHEME, TPM_RC_TYPE or TPM_RC_SIGNATURE
+// error may be returned at this point
+result = CryptVerifySignature(in->authObject, &authHash, &in->auth);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_PolicySigned_auth);
+}
+// Internal Data Update
+// Need the Name of the signing entity
+entityName.t.size = EntityGetName(in->authObject, &entityName.t.name);
+// Update policy with input policyRef and name of auth key
+// These values are updated even if the session is a trial session
+PolicyContextUpdate(TPM_CC_PolicySigned, &entityName, &in->policyRef,
+&in->cpHashA, authTimeout, session);
+// Command Output
+// Create ticket and timeout buffer if in->expiration < 0 and this is not
+// a trial session.
+// NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
+// when expiration is non-zero.
+if(
+in->expiration < 0
+&& session->attributes.isTrialPolicy == CLEAR
+)
+
+Page 238
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+
+Part 3: Commands
+
+{
+// Generate timeout buffer. The format of output timeout buffer is
+// TPM-specific.
+// Note: can't do a direct copy because the output buffer is a byte
+// array and it may not be aligned to accept a 64-bit value. The method
+// used has the side-effect of making the returned value a big-endian,
+// 64-bit value that is byte aligned.
+out->timeout.t.size = sizeof(UINT64);
+UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
+// Compute policy ticket
+TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
+authTimeout, &in->cpHashA, &in->policyRef, &entityName,
+&out->policyTicket);
+}
+else
+{
+// Generate a null ticket.
+// timeout buffer is null
+out->timeout.t.size = 0;
+// auth ticket is null
+out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
+out->policyTicket.hierarchy = TPM_RH_NULL;
+out->policyTicket.digest.t.size = 0;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 239
+October 31, 2013
+
+ Part 3: Commands
+
+25.4
+
+Trusted Platform Module Library
+
+TPM2_PolicySecret
+
+25.4.1 General Description
+This command includes a secret-based authorization to a policy. The caller proves knowledge of the
+secret value using an authorization session using the authValue associated with authHandle. A
+password session, an HMAC session, or a policy session containing TPM2_PolicyAuthValue() or
+TPM2_PolicyPassword() will satisfy this requirement.
+“If a policy session is used and use of the authValue of authHandle is not required, the TPM will return
+TPM_RC_MODE.”
+The secret is the authValue of authObject, which may be any TPM entity with a handle and an associated
+authValue. This includes the reserved handles (for example, Platform, Storage, and Endorsement), NV
+Indexes, and loaded objects.
+NOTE 1
+
+The authorization value for a hierarchy cannot be used in th is command if the hierarchy is disabled.
+
+If the authorization check fails, then the normal dictionary attack logic is invoked.
+If the authorization provided by the authorization session is valid, the command parameters are checked
+as described in 25.2.2.
+When all validations have succeeded, policySession→policyDigest is updated by PolicyUpdate() (see
+25.2.3).
+
+PolicyUpdate(TPM_CC_PolicySecret, authObject→Name, policyRef)
+
+(15)
+
+If the cpHashA command parameter is not an Empty Buffer, it is copied to cpHash in the session context.
+The TPM will optionally produce a ticket as described in 25.2.5.
+If the session is a trial session, policySession→policyDigest is updated as if the authorization is valid but
+no check is performed.
+NOTE 2
+
+If an HMAC is used to convey the authorization, a separate session is needed for the authorization.
+Because the HMAC in that authorization will include a nonce that prevents replay of the
+authorization, the value of the nonceTPM parameter in this command is limited. It is retained mostly
+to provide processing consistency with TPM2_PolicySigned().
+
+Page 240
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.4.2 Command and Response
+Table 115 — TPM2_PolicySecret Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+see clause 8
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicySecret
+
+TPMI_DH_ENTITY
+
+@authHandle
+
+handle for an entity providing the authorization
+Auth Index: 1
+Auth Role: USER
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_NONCE
+
+nonceTPM
+
+the policy nonce for the session
+If the nonce is not included in the authorization
+qualification, this field is the Empty Buffer.
+
+cpHashA
+
+digest of the command parameters to which this
+authorization is limited
+This not the cpHash for this command but the cpHash
+for the command to which this policy session will be
+applied. If it is not limited, the parameter will be the
+Empty Buffer.
+
+TPM2B_NONCE
+
+policyRef
+
+a reference to a policy relating to the authorization –
+may be the Empty Buffer
+Size is limited to be no larger than the nonce size
+supported on the TPM.
+
+INT32
+
+expiration
+
+time when authorization will expire, measured in
+seconds from the time that nonceTPM was generated
+If expiration is zero, a NULL Ticket is returned.
+
+TPM2B_DIGEST
+
+Table 116 — TPM2_PolicySecret Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_TIMEOUT
+
+timeout
+
+implementation-specific time value used to indicate to
+the TPM when the ticket expires; this ticket will use the
+TPMT_ST_AUTH_SECRET structure tag
+
+TPMT_TK_AUTH
+
+policyTicket
+
+produced if the command succeeds and expiration in
+the command was non-zero
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 241
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.4.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "PolicySecret_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+cpHash for policy was previously set to a value that is not the same
+as cpHashA
+
+TPM_RC_EXPIRED
+
+expiration indicates a time in the past
+
+TPM_RC_NONCE
+
+nonceTPM does not match the nonce associated with policySession
+
+TPM_RC_SIZE
+
+cpHashA is not the size of a digest for the hash associated with
+policySession
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+input policyID or expiration does not match the internal data in policy
+session
+
+TPM_RC
+TPM2_PolicySecret(
+PolicySecret_In
+PolicySecret_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+SESSION
+TPM2B_NAME
+UINT32
+
+result;
+*session;
+entityName;
+expiration = (in->expiration < 0)
+? -(in->expiration) : in->expiration;
+authTimeout = 0;
+
+)
+{
+
+UINT64
+// Input Validation
+
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+//Only do input validation if this is not a trial policy session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+if(expiration != 0)
+authTimeout = expiration * 1000 + session->startTime;
+result = PolicyParameterChecks(session, authTimeout,
+&in->cpHashA, &in->nonceTPM,
+RC_PolicySecret_nonceTPM,
+RC_PolicySecret_cpHashA,
+RC_PolicySecret_expiration);
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Internal Data Update
+// Need the name of the authorizing entity
+entityName.t.size = EntityGetName(in->authHandle, &entityName.t.name);
+// Update policy context with input policyRef and name of auth key
+// This value is computed even for trial sessions. Possibly update the cpHash
+PolicyContextUpdate(TPM_CC_PolicySecret, &entityName, &in->policyRef,
+
+Page 242
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+
+Part 3: Commands
+
+&in->cpHashA, authTimeout, session);
+// Command Output
+// Create ticket and timeout buffer if in->expiration < 0 and this is not
+// a trial session.
+// NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
+// when expiration is non-zero.
+if(
+in->expiration < 0
+&& session->attributes.isTrialPolicy == CLEAR
+)
+{
+// Generate timeout buffer. The format of output timeout buffer is
+// TPM-specific.
+// Note: can't do a direct copy because the output buffer is a byte
+// array and it may not be aligned to accept a 64-bit value. The method
+// used has the side-effect of making the returned value a big-endian,
+// 64-bit value that is byte aligned.
+out->timeout.t.size = sizeof(UINT64);
+UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
+// Compute policy ticket
+TicketComputeAuth(TPM_ST_AUTH_SECRET, EntityGetHierarchy(in->authHandle),
+authTimeout, &in->cpHashA, &in->policyRef,
+&entityName, &out->policyTicket);
+}
+else
+{
+// timeout buffer is null
+out->timeout.t.size = 0;
+// auth ticket is null
+out->policyTicket.tag = TPM_ST_AUTH_SECRET;
+out->policyTicket.hierarchy = TPM_RH_NULL;
+out->policyTicket.digest.t.size = 0;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 243
+October 31, 2013
+
+ Part 3: Commands
+
+25.5
+
+Trusted Platform Module Library
+
+TPM2_PolicyTicket
+
+25.5.1 General Description
+This command is similar to TPM2_PolicySigned() except that it takes a ticket instead of a signed
+authorization. The ticket represents a validated authorization that had an expiration time associated with
+it.
+The parameters of this command are checked as described in 25.2.2.
+If the checks succeed, the TPM uses the timeout, cpHashA, policyRef, and keyName to construct a ticket
+to compare with the value in ticket. If these tickets match, then the TPM will create a TPM2B_NAME
+(objectName) using authName and update the context of policySession by PolicyUpdate() (see 25.2.3).
+
+PolicyUpdate(commandCode, authName, policyRef)
+
+(16)
+
+If the structure tag of ticket is TPM_ST_AUTH_SECRET, then commandCode will be
+TPM_CC_PolicySecret. If the structure tag of ticket is TPM_ST_AUTH_SIGNED, then commandCode will
+be TPM_CC_PolicySIgned.
+If the cpHashA command parameter is not an Empty Buffer, it may be copied to cpHash in the session
+context.as described in 25.2.1.
+
+Page 244
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.5.2 Command and Response
+Table 117 — TPM2_PolicyTicket Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+see clause 8
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyTicket
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_TIMEOUT
+
+timeout
+
+time when authorization will expire
+The contents are TPM specific. This shall be the value
+returned when ticket was produced.
+
+TPM2B_DIGEST
+
+cpHashA
+
+digest of the command parameters to which this
+authorization is limited
+If it is not limited, the parameter will be the Empty
+Buffer.
+
+TPM2B_NONCE
+
+policyRef
+
+reference to a qualifier for the policy – may be the
+Empty Buffer
+
+TPM2B_NAME
+
+authName
+
+name of the object that provided the authorization
+
+TPMT_TK_AUTH
+
+ticket
+
+an authorization ticket returned by the TPM in response
+to a TPM2_PolicySigned() or TPM2_PolicySecret()
+
+Table 118 — TPM2_PolicyTicket Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 245
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "PolicyTicket_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+policy's cpHash was previously set to a different value
+
+TPM_RC_EXPIRED
+
+timeout value in the ticket is in the past and the ticket has expired
+
+TPM_RC_SIZE
+
+timeout or cpHash has invalid size for the
+
+TPM_RC_TICKET
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+ticket is not valid
+
+TPM_RC
+TPM2_PolicyTicket(
+PolicyTicket_In
+
+*in
+
+// IN: input parameter list
+
+TPM_RC
+SESSION
+UINT64
+TPMT_TK_AUTH
+TPM_CC
+
+result;
+*session;
+timeout;
+ticketToCompare;
+commandCode = TPM_CC_PolicySecret;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// NOTE: A trial policy session is not allowed to use this command.
+// A ticket is used in place of a previously given authorization. Since
+// a trial policy doesn't actually authenticate, the validated
+// ticket is not necessary and, in place of using a ticket, one
+// should use the intended authorization for which the ticket
+// would be a subsitute.
+if(session->attributes.isTrialPolicy)
+return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession;
+// Restore timeout data. The format of timeout buffer is TPM-specific.
+// In this implementation, we simply copy the value of timeout to the
+// buffer.
+if(in->timeout.t.size != sizeof(UINT64))
+return TPM_RC_SIZE + RC_PolicyTicket_timeout;
+timeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer);
+// Do the normal checks on the cpHashA and timeout values
+result = PolicyParameterChecks(session, timeout,
+&in->cpHashA, NULL,
+0,
+// no bad nonce return
+RC_PolicyTicket_cpHashA,
+RC_PolicyTicket_timeout);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Validate Ticket
+// Re-generate policy ticket by input parameters
+TicketComputeAuth(in->ticket.tag, in->ticket.hierarchy, timeout, &in->cpHashA,
+&in->policyRef, &in->authName, &ticketToCompare);
+
+Page 246
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
+Part 3: Commands
+
+// Compare generated digest with input ticket digest
+if(!Memory2BEqual(&in->ticket.digest.b, &ticketToCompare.digest.b))
+return TPM_RC_TICKET + RC_PolicyTicket_ticket;
+// Internal Data Update
+// Is this ticket to take the place of a TPM2_PolicySigned() or
+// a TPM2_PolicySecret()?
+if(in->ticket.tag == TPM_ST_AUTH_SIGNED)
+commandCode = TPM_CC_PolicySigned;
+else if(in->ticket.tag == TPM_ST_AUTH_SECRET)
+commandCode = TPM_CC_PolicySecret;
+else
+// There could only be two possible tag values. Any other value should
+// be caught by the ticket validation process.
+pAssert(FALSE);
+// Update policy context
+PolicyContextUpdate(commandCode, &in->authName, &in->policyRef,
+&in->cpHashA, timeout, session);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 247
+October 31, 2013
+
+ Part 3: Commands
+
+25.6
+
+Trusted Platform Module Library
+
+TPM2_PolicyOR
+
+25.6.1 General Description
+This command allows options in authorizations without requiring that the TPM evaluate all of the options.
+If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
+satisfies the policy. This command will indicate that one of the required sets of conditions has been
+satisfied.
+PolicySession→policyDigest is compared against the list of provided values. If the current
+policySession→policyDigest does not match any value in the list, the TPM shall return TPM_RC_VALUE.
+Otherwise, it will replace policySession→policyDigest with the digest of the concatenation of all of the
+digests and return TPM_RC_SUCCESS.
+If policySession is a trial session, the TPM will assume that policySession→policyDigest matches one of
+the list entries and compute the new value of policyDigest.
+The algorithm for computing the new value for policyDigest of policySession is:
+a) Concatenate all the digest values in pHashList:
+
+digests ≔ pHashList.digests[1].buffer || … || pHashList.digests[n].buffer
+NOTE 1
+
+(17)
+
+The TPM makes no check to see if the size of an entry matches the size of the digest of the
+policy.
+
+b) Reset policyDigest to a Zero Digest.
+c) Extend the command code and the hashes computed in step a) above:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyOR || digests)
+NOTE 2
+
+(18)
+
+The computation in b) and c) above is equivalent to:
+
+policyDigestnew ≔ HpolicyAlg(0…0 || TPM_CC_PolicyOR || digests)
+
+A TPM shall support a list with at least eight tagged digest values.
+NOTE 3
+
+If policies are to be portable between TPMs, then they should not use more than eight values.
+
+Page 248
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.6.2 Command and Response
+Table 119 — TPM2_PolicyOR Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyOR.
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPML_DIGEST
+
+pHashList
+
+the list of hashes to check for a match
+
+Table 120 — TPM2_PolicyOR Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 249
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "PolicyOR_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+no digest in pHashList matched the current value of policyDigest for
+policySession
+
+TPM_RC
+TPM2_PolicyOR(
+PolicyOR_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+UINT32
+
+*session;
+i;
+
+// Input Validation and Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Compare and Update Internal Session policy if match
+for(i = 0; i < in->pHashList.count; i++)
+{
+if(
+session->attributes.isTrialPolicy == SET
+|| (Memory2BEqual(&session->u2.policyDigest.b,
+&in->pHashList.digests[i].b))
+)
+{
+// Found a match
+HASH_STATE
+hashState;
+TPM_CC
+commandCode = TPM_CC_PolicyOR;
+// Start hash
+session->u2.policyDigest.t.size = CryptStartHash(session->authHashAlg,
+&hashState);
+// Set policyDigest to 0 string and add it to hash
+MemorySet(session->u2.policyDigest.t.buffer, 0,
+session->u2.policyDigest.t.size);
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add command code
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// Add each of the hashes in the list
+for(i = 0; i < in->pHashList.count; i++)
+{
+// Extend policyDigest
+CryptUpdateDigest2B(&hashState, &in->pHashList.digests[i].b);
+}
+// Complete digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+}
+// None of the values in the list matched the current policyDigest
+return TPM_RC_VALUE + RC_PolicyOR_pHashList;
+
+Page 250
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+
+Part 3: Commands
+
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 251
+October 31, 2013
+
+ Part 3: Commands
+
+25.7
+
+Trusted Platform Module Library
+
+TPM2_PolicyPCR
+
+25.7.1 General Description
+This command is used to cause conditional gating of a policy based on PCR. This allows one group of
+authorizations to occur when PCR are in one state and a different set of authorizations when the PCR are
+in a different state. 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 digest of the TPM PCR.
+The TPM will modify the pcrs parameter so that bits that correspond to unimplemented PCR are CLEAR.
+If policySession is not a trial policy session, the TPM will use the modified value of pcrs to select PCR
+values to hash according to Part 1, Selecting Multiple PCR. The hash algorithm of the policy session is
+used to compute a digest (digestTPM) of the selected PCR. If pcrDigest does not have a length of zero,
+then it is compared to digestTPM; and if the values do not match, the TPM shall return TPM_RC_VALUE
+and make no change to policySession→policyDigest. If the values match, or if the length of pcrDigest is
+zero, then policySession→policyDigest is extended by:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPCR || pcrs || digestTPM)
+
+(19)
+
+where
+
+pcrs
+
+the pcrs parameter with bits corresponding to unimplemented
+PCR set to 0
+
+digestTPM
+
+the digest of the selected PCR using the hash algorithm of the
+policy session
+
+NOTE 1
+
+If the caller provides the expected PCR value, the intention is that the policy evaluation stop at that
+point if the PCR do not match. If the caller does not provide the expected PCR value, then the
+validity of the settings will not be determined until an attempt is made to use the policy for
+authorization. If the policy is constructed such that the PCR check comes before user authorization
+checks, this early termination would allow software to avoid unnecessary prompts for user input to
+satisfy a policy that would fail later due to incorr ect PCR values.
+
+After this command completes successfully, the TPM shall return TPM_RC_PCR_CHANGED if the policy
+session is used for authorization and the PCR are not known to be correct.
+The TPM uses a “generation” number (pcrUpdateCounter) that is incremented each time PCR are
+updated (unless the PCR being changed is specified not to cause a change to this counter). The value of
+this counter is stored in the policy session context (policySession→pcrUpdateCounter) when this
+command is executed. When the policy is used for authorization, the current value of the counter is
+compared to the value in the policy session context and the authorization will fail if the values are not the
+same.
+When this command is executed, policySession→pcrUpdateCounter is checked to see if it has been
+previously set (in the reference implementation, it has a value of zero if not previously set). If it has been
+set, it will be compared with the current value of pcrUpdateCounter to determine if any PCR changes
+have occurred. If the values are different, the TPM shall return TPM_RC_PCR_CHANGED. If
+policySession→pcrUpdateCounter has not been set, then it is set to the current value of
+pcrUpdateCounter.
+If policySession is a trial policy session, the TPM will not check any PCR and will compute:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPCR || pcrs || pcrDigest)
+
+(20)
+
+In this computation, pcrs is the input parameter without modification.
+NOTE 2
+
+The pcrs parameter is expected to match the configuration of the TPM for which the policy is being
+computed which may not be the same as the TPM on which the trial policy is being computed.
+
+Page 252
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.7.2 Command and Response
+Table 121 — TPM2_PolicyPCR Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyPCR
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+pcrDigest
+
+expected digest value of the selected PCR using the
+hash algorithm of the session; may be zero length
+
+TPML_PCR_SELECTION
+
+pcrs
+
+the PCR to include in the check digest
+
+Table 122 — TPM2_PolicyPCR Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 253
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PolicyPCR_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+if provided, pcrDigest does not match the current PCR settings
+
+TPM_RC_PCR_CHANGED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+a previous TPM2_PolicyPCR() set pcrCounter and it has changed
+
+TPM_RC
+TPM2_PolicyPCR(
+PolicyPCR_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM2B_DIGEST
+BYTE
+UINT32
+BYTE
+TPM_CC
+HASH_STATE
+
+*session;
+pcrDigest;
+pcrs[sizeof(TPML_PCR_SELECTION)];
+pcrSize;
+*buffer;
+commandCode = TPM_CC_PolicyPCR;
+hashState;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Do validation for non trial session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// Make sure that this is not going to invalidate a previous PCR check
+if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter)
+return TPM_RC_PCR_CHANGED;
+// Compute current PCR digest
+PCRComputeCurrentDigest(session->authHashAlg, &in->pcrs, &pcrDigest);
+// If the caller specified the PCR digest and it does not
+// match the current PCR settings, return an error..
+if(in->pcrDigest.t.size != 0)
+{
+if(!Memory2BEqual(&in->pcrDigest.b, &pcrDigest.b))
+return TPM_RC_VALUE + RC_PolicyPCR_pcrDigest;
+}
+}
+else
+{
+// For trial session, just use the input PCR digest
+pcrDigest = in->pcrDigest;
+}
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(
+policyDigestold || TPM_CC_PolicyPCR
+//
+|| pcrs || pcrDigest)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+
+Page 254
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+Part 3: Commands
+
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add PCRS
+buffer = pcrs;
+pcrSize = TPML_PCR_SELECTION_Marshal(&in->pcrs, &buffer, NULL);
+CryptUpdateDigest(&hashState, pcrSize, pcrs);
+// add PCR digest
+CryptUpdateDigest2B(&hashState, &pcrDigest.b);
+// complete the hash and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update pcrCounter in session context for non trial session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+session->pcrCounter = gr.pcrCounter;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 255
+October 31, 2013
+
+ Part 3: Commands
+
+25.8
+
+Trusted Platform Module Library
+
+TPM2_PolicyLocality
+
+25.8.1 General Description
+This command indicates that the authorization will be limited to a specific locality.
+policySession→commandLocality is a parameter kept in the session context. It is initialized when the
+policy session is started to allow the policy to apply to any locality.
+If locality has a value greater than 31, then an extended locality is indicated. For an extended locality, the
+TPM will validate that policySession→commandLocality is has not previously been set or that the current
+value of policySession→commandLocality is the same as locality (TPM_RC_RANGE).
+When locality is not an extended locality, the TPM will validate that the policySession→commandLocality
+is not set or is not set to an extended locality value (TPM_RC_RANGE). If not the TPM will disable any
+locality not SET in the locality parameter. If the result of disabling localities results in no locality being
+enabled, the TPM will return TPM_RC_RANGE.
+If no error occurred in the validation of locality, policySession→policyDigest is extended with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyLocality || locality)
+
+(21)
+
+Then policySession→commandLocality is updated to indicate which localities are still allowed after
+execution of TPM2_PolicyLocality().
+When the policy session is used to authorize a command, the authorization will fail if the locality used for
+the command is not one of the enabled localities in policySession→commandLocality.
+
+Page 256
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.8.2 Command and Response
+Table 123 — TPM2_PolicyLocality Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyLocality
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPMA_LOCALITY
+
+locality
+
+the allowed localities for the policy
+
+Table 124 — TPM2_PolicyLocality Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 257
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.8.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PolicyLocality_fp.h"
+
+Limit a policy to a specific locality
+Error Returns
+TPM_RC_RANGE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+all the locality values selected by locality have been disabled by
+previous TPM2_PolicyLocality() calls.
+
+TPM_RC
+TPM2_PolicyLocality(
+PolicyLocality_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+BYTE
+BYTE
+UINT32
+BYTE
+TPM_CC
+HASH_STATE
+
+*session;
+marshalBuffer[sizeof(TPMA_LOCALITY)];
+prevSetting[sizeof(TPMA_LOCALITY)];
+marshalSize;
+*buffer;
+commandCode = TPM_CC_PolicyLocality;
+hashState;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Get new locality setting in canonical form
+buffer = marshalBuffer;
+marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, NULL);
+// Its an error if the locality parameter is zero
+if(marshalBuffer[0] == 0)
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// Get existing locality setting in canonical form
+buffer = prevSetting;
+TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
+// If the locality has been previously set, then it needs to be the same
+// tye as the input locality (i.e. both extended or both normal
+if(prevSetting[0] != 0 && ((prevSetting[0] <= 0) != (marshalBuffer[0] <= 0)))
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// See if the input is a regular or extended locality
+if(marshalBuffer[0] < 32)
+{
+// For regular locality
+// The previous setting must not be an extended locality
+if(prevSetting[0] > 31)
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// if there was no previous setting, start with all normal localities
+// enabled
+if(prevSetting[0] == 0)
+prevSetting[0] = 0x1F;
+// AND the new setting with the previous setting and store it in prevSetting
+
+Page 258
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+
+Part 3: Commands
+
+prevSetting[0] &= marshalBuffer[0];
+// The result setting can not be 0
+if(prevSetting[0] == 0)
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+}
+else
+{
+// for extended locality
+// if the locality has already been set, then it must match the
+if(prevSetting[0] != 0 && prevSetting[0] != marshalBuffer[0])
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// Setting is OK
+prevSetting[0] = marshalBuffer[0];
+}
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyLocality || locality)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add input locality
+CryptUpdateDigest(&hashState, marshalSize, marshalBuffer);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update session locality by unmarshal function. The function must succeed
+// because both input and existing locality setting have been validated.
+buffer = prevSetting;
+TPMA_LOCALITY_Unmarshal(&session->commandLocality, &buffer,
+(INT32 *) &marshalSize);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 259
+October 31, 2013
+
+ Part 3: Commands
+
+25.9
+
+Trusted Platform Module Library
+
+TPM2_PolicyNV
+
+25.9.1 General Description
+This command is used to cause conditional gating of a policy based on the contents of an NV Index.
+If policySession is a trial policy session, the TPM will update policySession→policyDigest as shown in
+equations (22) and (23) below and return TPM_RC_SUCCESS. It will not perform any validation. The
+remainder of this general description would apply only if policySession is not a trial policy session.
+An authorization session providing authorization to read the NV Index shall be provided.
+NOTE 1
+
+If read access is controlled by policy, the policy should include a branch that authorizes a
+TPM2_PolicyNV().
+
+If TPMA_NV_WRITTEN is not SET in the NV Index, the TPM shall return TPM_RC_NV_UNINITIALIZED.
+The TPM will validate that the size of operandB plus offset is not greater than the size of the NV Index. If
+it is, the TPM shall return TPM_RC_SIZE.
+The TPM will perform the indicated arithmetic check on the indicated portion of the selected NV Index. If
+the check fails, the TPM shall return TPM_RC_POLICY and not change policySession→policyDigest. If
+the check succeeds, the TPM will hash the arguments:
+
+args ≔ HpolicyAlg(operand.buffer || offset || operation)
+
+(22)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+operandB
+
+the value used for the comparison
+
+offset
+
+offset from the start of the NV Index data to start the comparison
+
+operation
+
+the operation parameter indicating the comparison being
+performed
+
+The value of args and the Name of the NV Index are extended to policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNV || args || nvIndex→Name)
+
+(23)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+args
+
+value computed in equation (22)
+
+nvIndex→Name
+
+the Name of the NV Index
+
+The signed arithmetic operations are performed using twos-compliment.
+Magnitude comparisons assume that the octet at offset zero in the referenced NV location and in
+operandB contain the most significant octet of the data.
+NOTE 2
+
+When an Index is written, it has a different authorization name than an Index that has not been
+written. It is possible to use this change in the NV Index to create a write-once Index.
+
+Page 260
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.9.2 Command and Response
+Table 125 — TPM2_PolicyNV Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyNV
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index of the area to read
+Auth Index: None
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_OPERAND
+
+operandB
+
+the second operand
+
+UINT16
+
+offset
+
+the offset in the NV Index for the start of operand A
+
+TPM_EO
+
+operation
+
+the comparison to make
+
+Table 126 — TPM2_PolicyNV Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 261
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.9.3 Detailed Actions
+1
+2
+3
+4
+
+#include
+#include
+#include
+#include
+
+"InternalRoutines.h"
+"PolicyNV_fp.h"
+"Policy_spt_fp.h"
+"NV_spt_fp.h"
+
+// Include NV support routine for read access check
+
+Error Returns
+TPM_RC_AUTH_TYPE
+
+NV index authorization type is not correct
+
+TPM_RC_NV_LOCKED
+
+NV index read locked
+
+TPM_RC_NV_UNINITIALIZED
+
+the NV index has not been initialized
+
+TPM_RC_POLICY
+
+the comparison to the NV contents failed
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+the size of nvIndex data starting at offset is less than the size of
+operandB
+
+TPM_RC
+TPM2_PolicyNV(
+PolicyNV_In
+
+*in
+
+// IN: input parameter list
+
+TPM_RC
+SESSION
+NV_INDEX
+BYTE
+TPM2B_NAME
+TPM_CC
+HASH_STATE
+TPM2B_DIGEST
+
+result;
+*session;
+nvIndex;
+nvBuffer[sizeof(in->operandB.t.buffer)];
+nvName;
+commandCode = TPM_CC_PolicyNV;
+hashState;
+argHash;
+
+)
+{
+
+// Input Validation
+// Get NV index information
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+//If this is a trial policy, skip all validations and the operation
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// NV Read access check. NV index should be allowed for read. A
+// TPM_RC_AUTH_TYPE or TPM_RC_NV_LOCKED error may be return at this
+// point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS) return result;
+// Valid NV data size should not be smaller than input operandB size
+if((nvIndex.publicArea.dataSize - in->offset) < in->operandB.t.size)
+return TPM_RC_SIZE + RC_PolicyNV_operandB;
+// Arithmetic Comparison
+// Get NV data. The size of NV data equals the input operand B size
+NvGetIndexData(in->nvIndex, &nvIndex, in->offset,
+in->operandB.t.size, nvBuffer);
+switch(in->operation)
+
+Page 262
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+
+Part 3: Commands
+
+{
+case TPM_EO_EQ:
+// compare A = B
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_NEQ:
+// compare A != B
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GT:
+// compare A > B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GT:
+// compare A > B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LT:
+// compare A < B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LT:
+// compare A < B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GE:
+// compare A >= B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GE:
+// compare A >= B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LE:
+// compare A <= B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LE:
+// compare A <= B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_BITSET:
+// All bits SET in B are SET in A. ((A&B)=B)
+{
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+!= 0)
+
+== 0)
+
+<= 0)
+
+<= 0)
+
+>= 0)
+
+>= 0)
+
+< 0)
+
+< 0)
+
+> 0)
+
+> 0)
+
+Page 263
+October 31, 2013
+
+ Part 3: Commands
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+
+Trusted Platform Module Library
+
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if((nvBuffer[i] & in->operandB.t.buffer[i])
+!= in->operandB.t.buffer[i])
+return TPM_RC_POLICY;
+}
+break;
+case TPM_EO_BITCLEAR:
+// All bits SET in B are CLEAR in A. ((A&B)=0)
+{
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if((nvBuffer[i] & in->operandB.t.buffer[i]) != 0)
+return TPM_RC_POLICY;
+}
+break;
+default:
+pAssert(FALSE);
+break;
+}
+}
+// Internal Data Update
+// Start argument hash
+argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
+// add operandB
+CryptUpdateDigest2B(&hashState, &in->operandB.b);
+// add offset
+CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
+// add operation
+CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
+// complete argument digest
+CryptCompleteHash2B(&hashState, &argHash.b);
+// Update policyDigest
+// Start digest
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add argument digest
+CryptUpdateDigest2B(&hashState, &argHash.b);
+// Adding nvName
+nvName.t.size = EntityGetName(in->nvIndex, &nvName.t.name);
+CryptUpdateDigest2B(&hashState, &nvName.b);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+
+Page 264
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.10 TPM2_PolicyCounterTimer
+25.10.1
+
+General Description
+
+This command is used to cause conditional gating of a policy based on the contents of the
+TPMS_TIME_INFO structure.
+If policySession is a trial policy session, the TPM will update policySession→policyDigest as shown in
+equations (24) and (25) below and return TPM_RC_SUCCESS. It will not perform any validation. The
+remainder of this general description would apply only if policySession is not a trial policy session.
+The TPM will perform the indicated arithmetic check on the indicated portion of the TPMS_TIME_INFO
+structure. If the check fails, the TPM shall return TPM_RC_POLICY and not change
+policySession→policyDigest. If the check succeeds, the TPM will hash the arguments:
+
+args ≔ HpolicyAlg(operandB.buffer || offset || operation)
+
+(24)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+operandB.buffer
+
+the value used for the comparison
+
+offset
+
+offset from the start of the TPMS_TIME_INFO structure at which
+the comparison starts
+
+operation
+
+the operation parameter indicating the comparison being
+performed
+
+The value of args is extended to policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCounterTimer || args)
+
+(25)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+args
+
+value computed in equation (24)
+
+The signed arithmetic operations are performed using twos-compliment.
+Magnitude comparisons assume that the octet at offset zero in the referenced location and in operandB
+contain the most significant octet of the data.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 265
+October 31, 2013
+
+ Part 3: Commands
+
+25.10.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 127 — TPM2_PolicyCounterTimer Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyCounterTimer
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_OPERAND
+
+operandB
+
+the second operand
+
+UINT16
+
+offset
+
+the offset in TPMS_TIME_INFO structure for the start of
+operand A
+
+TPM_EO
+
+operation
+
+the comparison to make
+
+Table 128 — TPM2_PolicyCounterTimer Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 266
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.10.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyCounterTimer_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_POLICY
+
+the comparison of the selected portion of the TPMS_TIME_INFO with
+operandB failed
+
+TPM_RC_RANGE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+
+offset + size exceed size of TPMS_TIME_INFO structure
+
+TPM_RC
+TPM2_PolicyCounterTimer(
+PolicyCounterTimer_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+SESSION
+TIME_INFO
+TPM_CC
+HASH_STATE
+TPM2B_DIGEST
+
+result;
+*session;
+infoData;
+// data buffer of TPMS_TIME_INFO
+commandCode = TPM_CC_PolicyCounterTimer;
+hashState;
+argHash;
+
+// Input Validation
+// If the command is going to use any part of the counter or timer, need
+// to verify that time is advancing.
+// The time and clock vales are the first two 64-bit values in the clock
+if(in->offset < <K>sizeof(UINT64) + sizeof(UINT64))
+{
+// Using Clock or Time so see if clock is running. Clock doesn't run while
+// NV is unavailable.
+// TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+//If this is a trial policy, skip all validations and the operation
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// Get time data info. The size of time info data equals the input
+// operand B size. A TPM_RC_RANGE error may be returned at this point
+result = TimeGetRange(in->offset, in->operandB.t.size, &infoData);
+if(result != TPM_RC_SUCCESS) return result;
+// Arithmetic Comparison
+switch(in->operation)
+{
+case TPM_EO_EQ:
+// compare A = B
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer) != 0)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_NEQ:
+// compare A != B
+if(CryptCompare(in->operandB.t.size, infoData,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 267
+October 31, 2013
+
+ Part 3: Commands
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+
+Trusted Platform Module Library
+
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GT:
+// compare A > B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GT:
+// compare A > B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LT:
+// compare A < B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LT:
+// compare A < B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GE:
+// compare A >= B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GE:
+// compare A >= B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LE:
+// compare A <= B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LE:
+// compare A <= B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_BITSET:
+// All bits SET in B are SET in A. ((A&B)=B)
+{
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if(
+(infoData[i] & in->operandB.t.buffer[i])
+!= in->operandB.t.buffer[i])
+return TPM_RC_POLICY;
+}
+break;
+case TPM_EO_BITCLEAR:
+// All bits SET in B are CLEAR in A. ((A&B)=0)
+{
+
+Page 268
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+== 0)
+
+<= 0)
+
+<= 0)
+
+>= 0)
+
+>= 0)
+
+< 0)
+
+< 0)
+
+> 0)
+
+> 0)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+
+Part 3: Commands
+
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if((infoData[i] & in->operandB.t.buffer[i]) != 0)
+return TPM_RC_POLICY;
+}
+break;
+default:
+pAssert(FALSE);
+break;
+}
+}
+// Internal Data Update
+// Start argument list hash
+argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
+// add operandB
+CryptUpdateDigest2B(&hashState, &in->operandB.b);
+// add offset
+CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
+// add operation
+CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
+// complete argument hash
+CryptCompleteHash2B(&hashState, &argHash.b);
+// update policyDigest
+// start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add argument digest
+CryptUpdateDigest2B(&hashState, &argHash.b);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 269
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.11 TPM2_PolicyCommandCode
+25.11.1
+
+General Description
+
+This command indicates that the authorization will be limited to a specific command code.
+If policySession→commandCode has its default value, then it will be set to code. If
+policySession→commandCode does not have its default value, then the TPM will return
+TPM_RC_VALUE if the two values are not the same.
+If code is not implemented, the TPM will return TPM_RC_POLICY_CC.
+If the TPM does not return an error, it will update policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCommandCode || code)
+
+(26)
+
+NOTE 1
+
+If a previous TPM2_PolicyCommandCode() had been executed, then it is probable that the policy
+expression is improperly formed but the TPM does not return an error.
+
+NOTE 2
+
+A TPM2_PolicyOR() would be used to allow an authorization to be used for multiple commands.
+
+When the policy session is used to authorize a command, the TPM will fail the command if the
+commandCode of that command does not match policySession→commandCode.
+This command, or TPM2_PolicyDuplicationSelect(), is required to enable the policy to be used for ADMIN
+role authorization.
+EXAMPLE
+
+Before TPM2_Certify() can
+TPM_CC_Certify is required.
+
+Page 270
+October 31, 2013
+
+be
+
+executed,
+
+TPM2_PolicyCommandCode()
+
+Published
+Copyright © TCG 2006-2013
+
+with
+
+code
+
+set
+
+to
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.11.2
+
+Part 3: Commands
+
+Command and Response
+Table 129 — TPM2_PolicyCommandCode Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyCommandCode
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM_CC
+
+code
+
+the allowed commandCode
+
+Table 130 — TPM2_PolicyCommandCode Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 271
+October 31, 2013
+
+ Part 3: Commands
+
+25.11.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyCommandCode_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+commandCode of policySession previously set to a different value
+
+TPM_RC
+TPM2_PolicyCommandCode(
+PolicyCommandCode_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyCommandCode;
+hashState;
+
+// Input validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+if(session->commandCode != 0 && session->commandCode != in->code)
+return TPM_RC_VALUE + RC_PolicyCommandCode_code;
+if(!CommandIsImplemented(in->code))
+return TPM_RC_POLICY_CC + RC_PolicyCommandCode_code;
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCommandCode || code)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add input commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &in->code);
+// complete the hash and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update commandCode value in session context
+session->commandCode = in->code;
+return TPM_RC_SUCCESS;
+}
+
+Page 272
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.12 TPM2_PolicyPhysicalPresence
+25.12.1
+
+General Description
+
+This command indicates that physical presence will need to be asserted at the time the authorization is
+performed.
+If this command is successful, policySession→isPPRequired will be SET to indicate that this check is
+required when the policy is used for authorization. Additionally, policySession→policyDigest is extended
+with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPhysicalPresence)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+(27)
+
+Page 273
+October 31, 2013
+
+ Part 3: Commands
+
+25.12.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 131 — TPM2_PolicyPhysicalPresence Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyPhysicalPresence
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+Table 132 — TPM2_PolicyPhysicalPresence Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 274
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.12.3
+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
+33
+34
+35
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyPhysicalPresence_fp.h"
+
+TPM_RC
+TPM2_PolicyPhysicalPresence(
+PolicyPhysicalPresence_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyPhysicalPresence;
+hashState;
+
+// Internal Data Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyPhysicalPresence)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update session attribute
+session->attributes.isPPRequired = SET;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 275
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.13 TPM2_PolicyCpHash
+25.13.1
+
+General Description
+
+This command is used to allow a policy to be bound to a specific command and command parameters.
+TPM2_PolicySigned(), TPM2_PolicySecret(), and TPM2_PolicyTIcket() are designed to allow an
+authorizing entity to execute an arbitrary command as the cpHashA parameter of those commands is not
+included in policySession→policyDigest. TPM2_PolicyCommandCode() allows the policy to be bound to a
+specific Command Code so that only certain entities may authorize specific command codes. This
+command allows the policy to be restricted such that an entity may only authorize a command with a
+specific set of parameters.
+If policySession→cpHash is already set and not the same as cpHashA, then the TPM shall return
+TPM_RC_VALUE. If cpHashA does not have the size of the policySession→policyDigest, the TPM shall
+return TPM_RC_SIZE.
+If the cpHashA checks succeed, policySession→cpHash
+policySession→policyDigest is updated with
+
+is
+
+set
+
+to
+
+cpHashA
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCpHash || cpHashA)
+
+Page 276
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+and
+(28)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.13.2
+
+Part 3: Commands
+
+Command and Response
+Table 133 — TPM2_PolicyCpHash Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyCpHash
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+cpHashA
+
+the cpHash added to the policy
+
+Table 134 — TPM2_PolicyCpHash Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 277
+October 31, 2013
+
+ Part 3: Commands
+
+25.13.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyCpHash_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+cpHash of policySession has previously been set to a different value
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+
+cpHashA is not the size of a digest produced by the hash algorithm
+associated with policySession
+
+TPM_RC
+TPM2_PolicyCpHash(
+PolicyCpHash_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyCpHash;
+hashState;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// A new cpHash is given in input parameter, but cpHash in session context
+// is not empty, or is not the same as the new cpHash
+if(
+in->cpHashA.t.size != 0
+&& session->u1.cpHash.t.size != 0
+&& !Memory2BEqual(&in->cpHashA.b, &session->u1.cpHash.b)
+)
+return TPM_RC_CPHASH;
+// A valid cpHash must have the same size as session hash digest
+if(in->cpHashA.t.size != CryptGetHashDigestSize(session->authHashAlg))
+return TPM_RC_SIZE + RC_PolicyCpHash_cpHashA;
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash || cpHashA)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add cpHashA
+CryptUpdateDigest2B(&hashState, &in->cpHashA.b);
+// complete the digest and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update cpHash in session context
+session->u1.cpHash = in->cpHashA;
+session->attributes.iscpHashDefined = SET;
+return TPM_RC_SUCCESS;
+
+Page 278
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+53
+
+Part 3: Commands
+
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 279
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.14 TPM2_PolicyNameHash
+25.14.1
+
+General Description
+
+This command allows a policy to be bound to a specific set of TPM entities without being bound to the
+parameters of the command. This is most useful for commands such as TPM2_Duplicate() and for
+TPM2_PCR_Event() when the referenced PCR requires a policy.
+The nameHash parameter should contain the digest of the Names associated with the handles to be used
+in the authorized command.
+EXAMPLE
+
+For the TPM2_Duplicate() command, two handles are provided. One is the handle of the object
+being duplicated and the other is the handle of the new parent. For that command, nameHash would
+contain:
+
+nameHash ≔ H policyAlg (objectHandle→Name || newParentHandle→Name)
+
+If policySession→cpHash is already set, the TPM shall return TPM_RC_VALUE. If the size of nameHash
+is not the size of policySession→policyDigest, the TPM shall return TPM_RC_SIZE. Otherwise,
+policySession→cpHash is set to nameHash.
+If this command completes successfully, the cpHash of the authorized command will not be used for
+validation. Only the digest of the Names associated with the handles in the command will be used.
+NOTE 1
+
+This allows the space normally
+policySession→nameHash instead.
+
+used
+
+to
+
+hold
+
+policySession→cpHash
+
+to
+
+be
+
+used
+
+for
+
+The policySession→policyDigest will be updated with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNameHash || nameHash)
+NOTE 2
+
+(29)
+
+This command will often be used with TPM2_PolicyAuthorize() where the owner of the object being
+duplicated provides approval for their object to be migrated to a specific new parent.
+
+Page 280
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.14.2
+
+Part 3: Commands
+
+Command and Response
+Table 135 — TPM2_PolicyNameHash Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyNameHash
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+nameHash
+
+the digest to be added to the policy
+
+Table 136 — TPM2_PolicyNameHash Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 281
+October 31, 2013
+
+ Part 3: Commands
+
+25.14.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyNameHash_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+nameHash has been previously set to a different value
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+
+nameHash is not the size of the digest produced by the hash
+algorithm associated with policySession
+
+TPM_RC
+TPM2_PolicyNameHash(
+PolicyNameHash_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyNameHash;
+hashState;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// A new nameHash is given in input parameter, but cpHash in session context
+// is not empty
+if(in->nameHash.t.size != 0 && session->u1.cpHash.t.size != 0)
+return TPM_RC_CPHASH;
+// A valid nameHash must have the same size as session hash digest
+if(in->nameHash.t.size != CryptGetHashDigestSize(session->authHashAlg))
+return TPM_RC_SIZE + RC_PolicyNameHash_nameHash;
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNameHash || nameHash)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add nameHash
+CryptUpdateDigest2B(&hashState, &in->nameHash.b);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// clear iscpHashDefined bit to indicate now this field contains a nameHash
+session->attributes.iscpHashDefined = CLEAR;
+// update nameHash in session context
+session->u1.cpHash = in->nameHash;
+return TPM_RC_SUCCESS;
+}
+
+Page 282
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.15 TPM2_PolicyDuplicationSelect
+25.15.1
+
+General Description
+
+This command allows qualification of duplication to allow duplication to a selected new parent.
+If this command not used in conjunction with TPM2_PolicyAuthorize(), then only the new parent is
+selected.
+EXAMPLE
+
+When an object is created when the list of allowed duplication targets is known, the policy would be
+created with includeObject CLEAR.
+
+NOTE 1
+
+Only the new parent may be selected because, without TPM2_PolicyAuthorize() , the Name of the
+Object to be duplicated would need to be known at the time that Object's policy is created. However,
+since the Name of the Object includes its policy, the Name is not known.
+
+If used in conjunction with TPM2_PolicyAuthorize(), then the authorizer of the new policy has the option
+of selecting just the new parent or of selecting both the new parent and the duplication Object..
+NOTE 2
+
+If the authorizing entity for an TPM2_PolicyAuthorize() only specifies the new parent, then that
+authorization may be applied to the duplication of any number of other Objects. If the authorizing
+entity specifies both a new parent and the duplicated Object, then the authorization only applies to
+that pairing of Object and new parent.
+
+If either policySession→cpHash or policySession→nameHash has been previously set, the TPM shall
+return TPM_RC_CPHASH. Otherwise, policySession→nameHash will be set to:
+
+nameHash ≔ HpolicyAlg(objectName || newParentName)
+
+(30)
+
+It is allowed that policySesion→nameHash and policySession→cpHash share the same memory
+space.
+
+NOTE 3
+
+The policySession→policyDigest will be updated according to the setting of includeObject. If equal to
+YES, policySession→policyDigest is updated by:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyDuplicationSelect ||
+objectName || newParentName || includeObject)
+
+(31)
+
+If includeObject is NO, policySession→policyDigest is updated by:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyDuplicationSelect ||
+newParentName || includeObject)
+NOTE 4
+
+(32)
+
+PolicySession→CpHash receives the digest of both Names so that the check performed in
+TPM2_Duplicate() may be the same regardless of which Names are included in
+policySession→policyDigest. This means that, when TPM2_PolicyDuplicationSelect() is executed, it
+is only valid for a specific pair of duplication object and new parent.
+
+If the command succeeds, commandCode in the policy session context is set to TPM_CC_Duplicate.
+NOTE 5
+
+The normal use of this command is before a TPM2_PolicyAuthorize(). An authorized entity would
+approve a policyDigest that allowed duplication to a specific new parent. The authorizing entity may
+want to limit the authorization so that the approval allows only a specific object to be duplicated to
+the new parent. In that case, the authorizing entity would approve the policyDigest of equation (31).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 283
+October 31, 2013
+
+ Part 3: Commands
+
+25.15.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 137 — TPM2_PolicyDuplicationSelect Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyDuplicationSelect
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_NAME
+
+objectName
+
+the Name of the object to be duplicated
+
+TPM2B_NAME
+
+newParentName
+
+the Name of the new parent
+
+TPMI_YES_NO
+
+includeObject
+
+if YES, the objectName will be included in the value in
+policySession→policyDigest
+
+Table 138 — TPM2_PolicyDuplicationSelect Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 284
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.15.3
+1
+2
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyDuplicationSelect_fp.h"
+Error Returns
+TPM_RC_COMMAND_CODE
+
+commandCode of 'policySession; is not empty
+
+TPM_RC_CPHASH
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+cpHash of policySession is not empty
+
+TPM_RC
+TPM2_PolicyDuplicationSelect(
+PolicyDuplicationSelect_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+HASH_STATE
+TPM_CC
+
+*session;
+hashState;
+commandCode = TPM_CC_PolicyDuplicationSelect;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// cpHash in session context must be empty
+if(session->u1.cpHash.t.size != 0)
+return TPM_RC_CPHASH;
+// commandCode in session context must be empty
+if(session->commandCode != 0)
+return TPM_RC_COMMAND_CODE;
+// Internal Data Update
+// Update name hash
+session->u1.cpHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
+// add objectName
+CryptUpdateDigest2B(&hashState, &in->objectName.b);
+// add new parent name
+CryptUpdateDigest2B(&hashState, &in->newParentName.b);
+// complete hash
+CryptCompleteHash2B(&hashState, &session->u1.cpHash.b);
+// update policy hash
+// Old policyDigest size should be the same as the new policyDigest size since
+// they are using the same hash algorithm
+session->u2.policyDigest.t.size
+= CryptStartHash(session->authHashAlg, &hashState);
+// add old policy
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add command code
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add objectName
+if(in->includeObject == YES)
+CryptUpdateDigest2B(&hashState, &in->objectName.b);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 285
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+
+Trusted Platform Module Library
+
+// add new parent name
+CryptUpdateDigest2B(&hashState, &in->newParentName.b);
+// add includeObject
+CryptUpdateDigestInt(&hashState, sizeof(TPMI_YES_NO), &in->includeObject);
+// complete digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// clear iscpHashDefined bit to indicate now this field contains a nameHash
+session->attributes.iscpHashDefined = CLEAR;
+// set commandCode in session context
+session->commandCode = TPM_CC_Duplicate;
+return TPM_RC_SUCCESS;
+}
+
+Page 286
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.16 TPM2_PolicyAuthorize
+25.16.1
+
+General Description
+
+This command allows policies to change. If a policy were static, then it would be difficult to add users to a
+policy. This command lets a policy authority sign a new policy so that it may be used in an existing policy.
+The authorizing entity signs a structure that contains
+
+aHash ≔ HaHashAlg(approvedPolicy || policyRef)
+
+(33)
+
+The aHashAlg is required to be the nameAlg of the key used to sign the aHash. The aHash value is then
+signed (symmetric or asymmetric) by keySign. That signature is then checked by the TPM in
+TPM2_VerifySignature() which produces a ticket by
+
+HMAC(proof, (TPM_ST_VERIFIED || aHash || keySign→Name))
+NOTE
+
+(34)
+
+The reason for the validation is because of the expectation that the policy will be used multiple times
+and it is more efficient to check a ticket than to load an object each time to chec k a signature.
+
+The ticket is then used in TPM2_PolicyAuthorize() to validate the parameters.
+The keySign parameter is required to be a valid object name using nameAlg other than TPM_ALG_NULL.
+If the first two octets of keySign are not a valid hash algorithm, the TPM shall return TPM_RC_HASH. If
+the remainder of the Name is not the size of the indicated digest, the TPM shall return TPM_RC_SIZE.
+The TPM validates that the approvedPolicy matches the current value of policySession→policyDigest and
+if not, shall return TPM_RC_VALUE.
+The TPM then validates that the parameters to TPM2_PolicyAuthorize() match the values used to
+generate the ticket. If so, the TPM will reset policySession→policyDigest to a Zero Digest. Then it will
+create a TPM2B_NAME (keyName) using keySign and update policySession→policyDigest with
+PolicyUpdate() (see 25.2.3).
+
+PolicyUpdate(TPM_CC_PolicyAuthorize, keyName, policyRef)
+
+(35)
+
+If the ticket is not valid, the TPM shall return TPM_RC_POLICY.
+If policySession is a trial session, policySession→policyDigest is extended as if the ticket is valid without
+actual verification.
+NOTE
+
+The unmarshaling process requires that a proper TPMT_TK_VERIFIED be provided for checkTicket
+but it may be a NULL Ticket.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 287
+October 31, 2013
+
+ Part 3: Commands
+
+25.16.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 139 — TPM2_PolicyAuthorize Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyAuthorize
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+approvedPolicy
+
+digest of the policy being approved
+
+TPM2B_NONCE
+
+policyRef
+
+a policy qualifier
+
+TPM2B_NAME
+
+keySign
+
+Name of a key that can sign a policy addition
+
+TPMT_TK_VERIFIED
+
+checkTicket
+
+ticket validating that approvedPolicy and policyRef were
+signed by keySign
+
+Table 140 — TPM2_PolicyAuthorize Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 288
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.16.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyAuthorize_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_HASH
+
+hash algorithm in keyName is not supported
+
+TPM_RC_SIZE
+
+keyName is not the correct size for its hash algorithm
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+Meaning
+
+the current policyDigest of policySession does not match
+approvedPolicy; or checkTicket doesn't match the provided values
+
+TPM_RC
+TPM2_PolicyAuthorize(
+PolicyAuthorize_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM2B_DIGEST
+HASH_STATE
+TPMT_TK_VERIFIED
+TPM_ALG_ID
+UINT16
+
+*session;
+authHash;
+hashState;
+ticket;
+hashAlg;
+digestSize;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Extract from the Name of the key, the algorithm used to compute it's Name
+hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
+// 'keySign' parameter needs to use a supported hash algorithm, otherwise
+// can't tell how large the digest should be
+digestSize = CryptGetHashDigestSize(hashAlg);
+if(digestSize == 0)
+return TPM_RC_HASH + RC_PolicyAuthorize_keySign;
+if(digestSize != (in->keySign.t.size - 2))
+return TPM_RC_SIZE + RC_PolicyAuthorize_keySign;
+//If this is a trial policy, skip all validations
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// Check that "approvedPolicy" matches the current value of the
+// policyDigest in policy session
+if(!Memory2BEqual(&session->u2.policyDigest.b,
+&in->approvedPolicy.b))
+return TPM_RC_VALUE + RC_PolicyAuthorize_approvedPolicy;
+// Validate ticket TPMT_TK_VERIFIED
+// Compute aHash. The authorizing object sign a digest
+// aHash := hash(approvedPolicy || policyRef).
+// Start hash
+authHash.t.size = CryptStartHash(hashAlg, &hashState);
+// add approvedPolicy
+CryptUpdateDigest2B(&hashState, &in->approvedPolicy.b);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 289
+October 31, 2013
+
+ Part 3: Commands
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+
+Trusted Platform Module Library
+
+// add policyRef
+CryptUpdateDigest2B(&hashState, &in->policyRef.b);
+// complete hash
+CryptCompleteHash2B(&hashState, &authHash.b);
+// re-compute TPMT_TK_VERIFIED
+TicketComputeVerified(in->checkTicket.hierarchy, &authHash,
+&in->keySign, &ticket);
+// Compare ticket digest. If not match, return error
+if(!Memory2BEqual(&in->checkTicket.digest.b, &ticket.digest.b))
+return TPM_RC_VALUE+ RC_PolicyAuthorize_checkTicket;
+}
+// Internal Data Update
+// Set policyDigest to zero digest
+MemorySet(session->u2.policyDigest.t.buffer, 0,
+session->u2.policyDigest.t.size);
+// Update policyDigest
+PolicyContextUpdate(TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef,
+NULL, 0, session);
+return TPM_RC_SUCCESS;
+}
+
+Page 290
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.17 TPM2_PolicyAuthValue
+25.17.1
+
+General Description
+
+This command allows a policy to be bound to the authorization value of the authorized object.
+When this command completes successfully, policySession→isAuthValueNeeded is SET to indicate that
+the authValue will be included in hmacKey when the authorization HMAC is computed for this session.
+Additionally, policySession→isPasswordNeeded will be CLEAR.
+NOTE
+
+If a policy does not use this command, then the hmacKey for the authorized command would only
+use sessionKey. If sessionKey is not present, then the hmacKey is an Empty Buffer and no HMAC
+would be computed.
+
+If successful, policySession→policyDigest will be updated with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyAuthValue)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+(36)
+
+Page 291
+October 31, 2013
+
+ Part 3: Commands
+
+25.17.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 141 — TPM2_PolicyAuthValue Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyAuthValue
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+Table 142 — TPM2_PolicyAuthValue Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 292
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.17.3
+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
+33
+34
+35
+36
+37
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyAuthValue_fp.h"
+#include "Policy_spt_fp.h"
+
+TPM_RC
+TPM2_PolicyAuthValue(
+PolicyAuthValue_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyAuthValue;
+hashState;
+
+)
+{
+
+// Internal Data Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue)
+//
+Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// complete the hash and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update isAuthValueNeeded bit in the session context
+session->attributes.isAuthValueNeeded = SET;
+session->attributes.isPasswordNeeded = CLEAR;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 293
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.18 TPM2_PolicyPassword
+25.18.1
+
+General Description
+
+This command allows a policy to be bound to the authorization value of the authorized object.
+When this command completes successfully, policySession→isPasswordNeeded is SET to indicate that
+authValue of the authorized object will be checked when the session is used for authorization. The caller
+will provide the authValue in clear text in the hmac parameter of the authorization. The comparison of
+hmac to authValue is performed as if the authorization is a password.
+NOTE 1
+
+The parameter field in the policy session where the authorization value is provided is called hmac. If
+TPM2_PolicyPassword() is part of the sequence, then the field will contain a password and not an
+HMAC.
+
+If successful, policySession→policyDigest will be updated with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyAuthValue)
+NOTE 2
+
+(37)
+
+This is the same extend value as used with TPM2_PolicyAuthValue so that the evaluation may be
+done using either an HMAC or a password with no change to the authPolicy of the object. The
+reason that two commands are present is to indicate to the TPM if the hmac field in the authorization
+will contain an HMAC or a password value.
+
+When this command is successful, policySession→isAuthValueNeeded will be CLEAR.
+
+Page 294
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.18.2
+
+Part 3: Commands
+
+Command and Response
+Table 143 — TPM2_PolicyPassword Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyPassword
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+Table 144 — TPM2_PolicyPassword Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 295
+October 31, 2013
+
+ Part 3: Commands
+
+25.18.3
+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
+33
+34
+35
+36
+37
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyPassword_fp.h"
+#include "Policy_spt_fp.h"
+
+TPM_RC
+TPM2_PolicyPassword(
+PolicyPassword_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyAuthValue;
+hashState;
+
+)
+{
+
+// Internal Data Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// Update isPasswordNeeded bit
+session->attributes.isPasswordNeeded = SET;
+session->attributes.isAuthValueNeeded = CLEAR;
+return TPM_RC_SUCCESS;
+}
+
+Page 296
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.19 TPM2_PolicyGetDigest
+25.19.1
+
+General Description
+
+This command returns the current policyDigest of the session. This command allows the TPM to be used
+to perform the actions required to pre-compute the authPolicy for an object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 297
+October 31, 2013
+
+ Part 3: Commands
+
+25.19.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 145 — TPM2_PolicyGetDigest Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyGetDigest
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session
+Auth Index: None
+
+Table 146 — TPM2_PolicyGetDigest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+policyDigest
+
+Page 298
+October 31, 2013
+
+the current value of the policySession→policyDigest
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.19.3
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyGetDigest_fp.h"
+
+TPM_RC
+TPM2_PolicyGetDigest(
+PolicyGetDigest_In
+PolicyGetDigest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+SESSION
+
+*session;
+
+// Command Output
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+out->policyDigest = session->u2.policyDigest;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 299
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.20 TPM2_PolicyNvWritten
+25.20.1
+
+General Description
+
+This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a deferred
+assertion. Values are stored in the policy session context and checked when the policy is used for
+authorization.
+If policySession→checkNVWritten is CLEAR, it is SET and policySession→nvWrittenState is set to
+writtenSet.
+If policySession→checkNVWritten is SET, the TPM will return TPM_RC_VALUE if
+policySession→nvWrittenState and writtenSet are not the same.
+If the TPM does not return and error, it will update policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNvWritten || writtenSet)
+
+(38)
+
+When the policy session is used to authorize a command, the TPM will fail the command if
+policySession→checkNVWritten is SET and nvIndex→attributes→TPMA_NV_WRITTEN does not match
+policySession→nvWrittenState.
+NOTE
+
+A typical use case is a simple policy for the first write during manufacturing provisioning that would
+require TPMA_NV_WRITTEN CLEAR and a more complex policy for later use that would require
+TPMA_NV_WRITTEN SET.
+
+Page 300
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.20.2
+
+Part 3: Commands
+
+Command and Response
+Table 147 — TPM2_PolicyNvWritten Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+Tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyNVWritten
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPMI_YES_NO
+
+writtenSet
+
+YES if NV Index is required to have been written
+NO if NV Index is required not to have been written
+
+Table 148 — TPM2_PolicyNvWritten Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+Tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 301
+October 31, 2013
+
+ Part 3: Commands
+
+25.20.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyNvWritten_fp.h"
+
+Make an NV Index policy dependent on the state of the TPMA_NV_WRITTEN attribute of the index.
+Error Returns
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+a conflicting request for the attribute has already been processed
+
+TPM_RC
+TPM2_PolicyNvWritten(
+PolicyNvWritten_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyNvWritten;
+hashState;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// If already set is this a duplicate (the same setting)? If it
+// is a conflicting setting, it is an error
+if(session->attributes.checkNvWritten == SET)
+{
+if((
+(session->attributes.nvWrittenState == SET)
+!= (in->writtenSet == YES)))
+return TPM_RC_VALUE + RC_PolicyNvWritten_writtenSet;
+}
+// Internal Data Update
+// Set session attributes so that the NV Index needs to be checked
+session->attributes.checkNvWritten = SET;
+session->attributes.nvWrittenState = (in->writtenSet == YES);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNvWritten
+//
+|| writtenSet)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add the byte of writtenState
+CryptUpdateDigestInt(&hashState, sizeof(TPMI_YES_NO), &in->writtenSet);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+
+Page 302
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Part 3: Commands
+
+Published
+Copyright © TCG 2006-2013
+
+Page 303
+October 31, 2013
+
+ Part 3: Commands
+
+26
+
+Trusted Platform Module Library
+
+Hierarchy Commands
+
+26.1
+
+TPM2_CreatePrimary
+
+26.1.1 General Description
+This command is used to create a Primary Object under one of the Primary Seeds or a Temporary Object
+under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for the object to be created.
+The command will create and load a Primary Object. The sensitive area is not returned.
+NOTE:
+
+Since the sensitive data is not returned, the key cannot be reloaded.
+persistent or it can be recreated.
+
+It can either be made
+
+Any type of object and attributes combination that is allowed by TPM2_Create() may be created by this
+command. The constraints on templates and parameters are the same as TPM2_Create() except that a
+Primary Storage Key and a Temporary Storage Key are not constrained to use the algorithms of their
+parents.
+For setting of the attributes of the created object, fixedParent, fixedTPM, userWithAuth, adminWithPolicy,
+encrypt, and restricted are implied to be SET in the parent (a Permanent Handle). The remaining
+attributes are implied to be CLEAR.
+The TPM will derive the object from the Primary Seed indicated in primaryHandle using an approved
+KDF. All of the bits of the template are used in the creation of the Primary Key. Methods for creating a
+Primary Object from a Primary Seed are described in Part 1 of this specification and implemented in Part
+4.
+If this command is called multiple times with the same inPublic parameter, inSensitive.data, and Primary
+Seed, the TPM shall produce the same Primary Object.
+NOTE
+
+If the Primary Seed is changed, the Primary Objects generated with the new seed shall be
+statistically unique even if the parameters of the call are the same.
+
+This command requires authorization. Authorization for a Primary Object attached to the Platform Primary
+Seed (PPS) shall be provided by platformAuth or platformPolicy. Authorization for a Primary Object
+attached to the Storage Primary Seed (SPS) shall be provided by ownerAuth or ownerPolicy.
+Authorization for a Primary Key attached to the Endorsement Primary Seed (EPS) shall be provided by
+endorsementAuth or endorsementPolicy.
+
+Page 304
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.1.2 Command and Response
+Table 149 — TPM2_CreatePrimary Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_CreatePrimary
+
+TPMI_RH_HIERARCHY+
+
+@primaryHandle
+
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER,
+TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_SENSITIVE_CREATE
+
+inSensitive
+
+the sensitive data, see Part 1 Sensitive Values
+
+TPM2B_PUBLIC
+
+inPublic
+
+the public template
+
+TPM2B_DATA
+
+outsideInfo
+
+data that will be included in the creation data for this
+object to provide permanent, verifiable linkage between
+this object and some object owner data
+
+TPML_PCR_SELECTION
+
+creationPCR
+
+PCR that will be used in creation data
+
+Table 150 — TPM2_CreatePrimary Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM_HANDLE
+
+objectHandle
+
+Handle for created Primary Object
+
+TPM2B_PUBLIC
+
+outPublic
+
+the public portion of the created object
+
+TPM2B_CREATION_DATA
+
+creationData
+
+contains a TPMT_CREATION_DATA
+
+TPM2B_DIGEST
+
+creationHash
+
+digest of creationData using nameAlg of outPublic
+
+TPMT_TK_CREATION
+
+creationTicket
+
+ticket used by TPM2_CertifyCreation() to validate that
+the creation data was produced by the TPM
+
+TPM2B_NAME
+
+name
+
+the name of the created object
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 305
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.1.3 Detailed Actions
+1
+2
+3
+4
+
+#include
+#include
+#include
+#include
+
+"InternalRoutines.h"
+"CreatePrimary_fp.h"
+"Object_spt_fp.h"
+<Platform.h>
+
+Error Returns
+TPM_RC_ATTRIBUTES
+
+sensitiveDataOrigin is CLEAR when 'sensitive. data' is an Empty
+Buffer, or is SET when 'sensitive. data' is not empty; fixedTPM,
+fixedParent, or encryptedDuplication attributes are inconsistent
+between themselves or with those of the parent object; inconsistent
+restricted, decrypt and sign attributes; attempt to inject sensitive data
+for an asymmetric key; attempt to create a symmetric cipher key that
+is not a decryption key
+
+TPM_RC_KDF
+
+incorrect KDF specified for decrypting keyed hash object
+
+TPM_RC_OBJECT_MEMORY
+
+there is no free slot for the object
+
+TPM_RC_SCHEME
+
+inconsistent attributes decrypt, sign, restricted and key's scheme ID;
+or hash algorithm is inconsistent with the scheme ID for keyed hash
+object
+
+TPM_RC_SIZE
+
+size of public auth policy or sensitive auth value does not match
+digest size of the name algorithm sensitive data size for the keyed
+hash object is larger than is allowed for the scheme
+
+TPM_RC_SYMMETRIC
+
+a storage key with no symmetric algorithm specified; or non-storage
+key with symmetric algorithm different from TPM_ALG_NULL
+
+TPM_RC_TYPE
+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
+33
+
+Meaning
+
+unknown object type;
+
+TPM_RC
+TPM2_CreatePrimary(
+CreatePrimary_In
+CreatePrimary_Out
+)
+{
+// Local variables
+TPM_RC
+TPMT_SENSITIVE
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+result = TPM_RC_SUCCESS;
+sensitive;
+
+// Input Validation
+// The sensitiveDataOrigin attribute must be consistent with the setting of
+// the size of the data object in inSensitive.
+if(
+(in->inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin == SET)
+!= (in->inSensitive.t.sensitive.data.t.size == 0 ))
+// Mismatch between the object attributes and the parameter.
+return TPM_RC_ATTRIBUTES + RC_CreatePrimary_inSensitive;
+// Check attributes in input public area. TPM_RC_ATTRIBUTES, TPM_RC_KDF,
+// TPM_RC_SCHEME, TPM_RC_SIZE, TPM_RC_SYMMETRIC, or TPM_RC_TYPE error may
+// be returned at this point.
+result = PublicAttributesValidation(FALSE, in->primaryHandle,
+&in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_CreatePrimary_inPublic);
+// Validate the sensitive area values
+if( MemoryRemoveTrailingZeros(&in->inSensitive.t.sensitive.userAuth)
+> CryptGetHashDigestSize(in->inPublic.t.publicArea.nameAlg))
+
+Page 306
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+
+Part 3: Commands
+
+return TPM_RC_SIZE + RC_CreatePrimary_inSensitive;
+// Command output
+// Generate Primary Object
+// The primary key generation process uses the Name of the input public
+// template to compute the key. The keys are generated from the template
+// before anything in the template is allowed to be changed.
+// A TPM_RC_KDF, TPM_RC_SIZE error may be returned at this point
+result = CryptCreateObject(in->primaryHandle, &in->inPublic.t.publicArea,
+&in->inSensitive.t.sensitive,&sensitive);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Fill in creation data
+FillInCreationData(in->primaryHandle, in->inPublic.t.publicArea.nameAlg,
+&in->creationPCR, &in->outsideInfo, &out->creationData,
+&out->creationHash);
+// Copy public area
+out->outPublic = in->inPublic;
+// Fill in private area for output
+ObjectComputeName(&(out->outPublic.t.publicArea), &out->name);
+// Compute creation ticket
+TicketComputeCreation(EntityGetHierarchy(in->primaryHandle), &out->name,
+&out->creationHash, &out->creationTicket);
+// Create a internal object. A TPM_RC_OBJECT_MEMORY error may be returned
+// at this point.
+result = ObjectLoad(in->primaryHandle, &in->inPublic.t.publicArea, &sensitive,
+&out->name, in->primaryHandle, TRUE, &out->objectHandle);
+return result;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 307
+October 31, 2013
+
+ Part 3: Commands
+
+26.2
+
+Trusted Platform Module Library
+
+TPM2_HierarchyControl
+
+26.2.1 General Description
+This command enables and disables use of a hierarchy and its associated NV storage. The command
+allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the proper authorization is
+provided.
+This command may be used to CLEAR phEnable and phEnableNV if platformAuth/platformPolicy is
+provided. phEnable may not be SET using this command.
+This command may be used to CLEAR shEnable if either platformAuth/platformPolicy
+ownerAuth/ownerPolicy is provided. shEnable may be SET if platformAuth/platformPolicy is provided.
+
+or
+
+This command may be used to CLEAR ehEnable if either platformAuth/platformPolicy or
+endorsementAuth/endorsementPolicy is provided. ehEnable may be SET if platformAuth/platformPolicy is
+provided.
+When this command is used to CLEAR phEnable, shEnable, or ehEnable, the TPM will disable use of
+any persistent entity associated with the disabled hierarchy and will flush any transient objects associated
+with the disabled hierarchy.
+When this command is used to CLEAR shEnable, the TPM will disable access to any NV index that has
+TPMA_NV_PLATFORMCREATE CLEAR (indicating that the NV Index was defined using ownerAuth). As
+long as shEnable is CLEAR, the TPM will return an error in response to any command that attempts to
+operate upon an NV index that has TPMA_NV_PLATFORMCREATE CLEAR.
+When this command is used to CLEAR phEnableNV, the TPM will disable access to any NV index that
+has TPMA_NV_PLATFORMCREATE SET (indicating that the NV Index was defined using platformAuth).
+As long as phEnableNV is CLEAR, the TPM will return an error in response to any command that
+attempts to operate upon an NV index that has TPMA_NV_PLATFORMCREATE SET.
+
+Page 308
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.2.2 Command and Response
+Table 151 — TPM2_HierarchyControl Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HierarchyControl {NV E}
+
+TPMI_RH_HIERARCHY
+
+@authHandle
+
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER or
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_ENABLES
+
+enable
+
+the enable being modified
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER,
+TPM_RH_PLATFORM, or TPM_RH_PLATFORM_NV
+
+TPMI_YES_NO
+
+state
+
+YES if the enable should be SET, NO if the enable
+should be CLEAR
+
+Table 152 — TPM2_HierarchyControl Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 309
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HierarchyControl_fp.h"
+Error Returns
+TPM_RC_AUTH_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+authHandle is not applicable to hierarchy in its current state
+
+TPM_RC
+TPM2_HierarchyControl(
+HierarchyControl_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+BOOL
+BOOL
+
+result;
+select = (in->state == YES);
+*selected = NULL;
+
+// Input Validation
+switch(in->enable)
+{
+// Platform hierarchy has to be disabled by platform auth
+// If the platform hierarchy has already been disabled, only a reboot
+// can enable it again
+case TPM_RH_PLATFORM:
+case TPM_RH_PLATFORM_NV:
+if(in->authHandle != TPM_RH_PLATFORM)
+return TPM_RC_AUTH_TYPE;
+break;
+// ShEnable may be disabled if PlatformAuth/PlatformPolicy or
+// OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it
+// may only be enabled if PlatformAuth/PlatformPolicy is provided.
+case TPM_RH_OWNER:
+if(
+in->authHandle != TPM_RH_PLATFORM
+&& in->authHandle != TPM_RH_OWNER)
+return TPM_RC_AUTH_TYPE;
+if(
+gc.shEnable == FALSE && in->state == YES
+&& in->authHandle != TPM_RH_PLATFORM)
+return TPM_RC_AUTH_TYPE;
+break;
+// EhEnable may be disabled if either PlatformAuth/PlatformPolicy or
+// EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled,
+// then it may only be enabled if PlatformAuth/PlatformPolicy is
+// provided.
+case TPM_RH_ENDORSEMENT:
+if(
+in->authHandle != TPM_RH_PLATFORM
+&& in->authHandle != TPM_RH_ENDORSEMENT)
+return TPM_RC_AUTH_TYPE;
+if(
+gc.ehEnable == FALSE && in->state == YES
+&& in->authHandle != TPM_RH_PLATFORM)
+return TPM_RC_AUTH_TYPE;
+break;
+default:
+pAssert(FALSE);
+break;
+}
+// Internal Data Update
+
+Page 310
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
+Part 3: Commands
+
+// Enable or disable the selected hierarchy
+// Note: the authorization processing for this command may keep these
+// command actions from being executed. For example, if phEnable is
+// CLEAR, then platformAuth cannot be used for authorization. This
+// means that would not be possible to use platformAuth to change the
+// state of phEnable from CLEAR to SET.
+// If it is decided that platformPolicy can still be used when phEnable
+// is CLEAR, then this code could SET phEnable when proper platform
+// policy is provided.
+switch(in->enable)
+{
+case TPM_RH_OWNER:
+selected = &gc.shEnable;
+break;
+case TPM_RH_ENDORSEMENT:
+selected = &gc.ehEnable;
+break;
+case TPM_RH_PLATFORM:
+selected = &g_phEnable;
+break;
+case TPM_RH_PLATFORM_NV:
+selected = &gc.phEnableNV;
+break;
+default:
+pAssert(FALSE);
+break;
+}
+if(selected != NULL && *selected != select)
+{
+// Before changing the internal state, make sure that NV is available.
+// Only need to update NV if changing the orderly state
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// state is changing and NV is available so modify
+*selected = select;
+// If a hierarchy was just disabled, flush it
+if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV)
+// Flush hierarchy
+ObjectFlushHierarchy(in->enable);
+// orderly state should be cleared because of the update to state clear data
+// This gets processed in ExecuteCommand() on the way out.
+g_clearOrderly = TRUE;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 311
+October 31, 2013
+
+ Part 3: Commands
+
+26.3
+
+Trusted Platform Module Library
+
+TPM2_SetPrimaryPolicy
+
+26.3.1 General Description
+This command allows setting of the authorization policy for the platform hierarchy (platformPolicy), the
+storage hierarchy (ownerPolicy), and the endorsement hierarchy (endorsementPolicy).
+The command requires an authorization session. The session shall use the current authValue or satisfy
+the current authPolicy for the referenced hierarchy.
+The policy that is changed is the policy associated with authHandle.
+If the enable associated with authHandle is not SET, then the associated authorization values (authValue
+or authPolicy) may not be used.
+
+Page 312
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.3.2 Command and Response
+Table 153 — TPM2_SetPrimaryPolicy Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SetPrimaryPolicy {NV}
+
+TPMI_RH_HIERARCHY
+
+@authHandle
+
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER or
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+authPolicy
+
+an authorization policy digest; may be the Empty Buffer
+If hashAlg is TPM_ALG_NULL, then this shall be an
+Empty Buffer.
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+the hash algorithm to use for the policy
+If the authPolicy is an Empty Buffer, then this field shall
+be TPM_ALG_NULL.
+
+Table 154 — TPM2_SetPrimaryPolicy Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 313
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "SetPrimaryPolicy_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+size of input authPolicy is not consistent with input hash algorithm
+
+TPM_RC
+TPM2_SetPrimaryPolicy(
+SetPrimaryPolicy_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input Validation
+// Check the authPolicy consistent with hash algorithm
+if(
+in->authPolicy.t.size != 0
+&& in->authPolicy.t.size != CryptGetHashDigestSize(in->hashAlg))
+return TPM_RC_SIZE + RC_SetPrimaryPolicy_authPolicy;
+// The command need NV update for OWNER and ENDORSEMENT hierarchy, and
+// might need orderlyState update for PLATFROM hierarchy.
+// Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
+// error may be returned at this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+// Set hierarchy policy
+switch(in->authHandle)
+{
+case TPM_RH_OWNER:
+gp.ownerAlg = in->hashAlg;
+gp.ownerPolicy = in->authPolicy;
+NvWriteReserved(NV_OWNER_ALG, &gp.ownerAlg);
+NvWriteReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
+break;
+case TPM_RH_ENDORSEMENT:
+gp.endorsementAlg = in->hashAlg;
+gp.endorsementPolicy = in->authPolicy;
+NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
+NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
+break;
+case TPM_RH_PLATFORM:
+gc.platformAlg = in->hashAlg;
+gc.platformPolicy = in->authPolicy;
+// need to update orderly state
+g_clearOrderly = TRUE;
+break;
+default:
+pAssert(FALSE);
+break;
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 314
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+26.4
+
+Part 3: Commands
+
+TPM2_ChangePPS
+
+26.4.1 General Description
+This replaces the current PPS with a value from the RNG and sets platformPolicy to the default
+initialization value (the Empty Buffer).
+NOTE 1
+
+A policy that is the Empty Buffer can match no policy.
+
+NOTE 2
+
+platformAuth is not changed.
+
+All loaded transient and persistent objects in the Platform hierarchy are flushed.
+Saved contexts in the Platform hierarchy that were created under the old PPS will no longer be able to be
+loaded.
+The policy hash algorithm for PCR is reset to TPM_ALG_NULL.
+This command does not clear any NV Index values.
+NOTE 3
+
+Index values belonging to the Platform are preserved because the indexes may have configuration
+information that will be the same after the PPS changes. The Platform may remove the indexes that
+are no longer needed using TPM2_NV_UndefineSpace().
+
+This command requires platformAuth.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 315
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.4.2 Command and Response
+Table 155 — TPM2_ChangePPS Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ChangePPS {NV E}
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_PLATFORM
+
+Description
+
+Table 156 — TPM2_ChangePPS Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 316
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.4.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+#include "InternalRoutines.h"
+#include "ChangePPS_fp.h"
+
+TPM_RC
+TPM2_ChangePPS(
+ChangePPS_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+TPM_RC
+
+i;
+result;
+
+// Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
+// error may be returned at this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input parameter is not reference in command action
+in = NULL;
+// Internal Data Update
+// Reset platform hierarchy seed from RNG
+CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.PPSeed.t.buffer);
+// Create a new phProof value from RNG to prevent the saved platform
+// hierarchy contexts being loaded
+CryptGenerateRandom(PROOF_SIZE, gp.phProof.t.buffer);
+// Set platform authPolicy to null
+gc.platformAlg = TPM_ALG_NULL;
+gc.platformPolicy.t.size = 0;
+// Flush loaded object in platform hierarchy
+ObjectFlushHierarchy(TPM_RH_PLATFORM);
+// Flush platform evict object and index in NV
+NvFlushHierarchy(TPM_RH_PLATFORM);
+// Save hierarchy changes to NV
+NvWriteReserved(NV_PP_SEED, &gp.PPSeed);
+NvWriteReserved(NV_PH_PROOF, &gp.phProof);
+// Re-initialize PCR policies
+for(i = 0; i < NUM_POLICY_PCR_GROUP; i++)
+{
+gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
+gp.pcrPolicies.policy[i].t.size = 0;
+}
+NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
+// orderly state should be cleared because of the update to state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 317
+October 31, 2013
+
+ Part 3: Commands
+
+26.5
+
+Trusted Platform Module Library
+
+TPM2_ChangeEPS
+
+26.5.1 General Description
+This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to
+their default initialization values: ehEnable is SET, endorsementAuth and endorsementPolicy both equal
+to the Empty Buffer. It will flush any loaded objects in the EPS hierarchy and not allow objects in the
+hierarchy associated with the previous EPS to be loaded.
+NOTE
+
+In the reference implementation, ehProof is a non-volatile value from the RNG. It is allowed that the
+ehProof be generated by a KDF using both the EPS and SPS as inputs. If generated with a KDF, the
+ehProof can be generated on an as-needed basis or made a non-volatile value.
+
+This command requires platformAuth.
+
+Page 318
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.5.2 Command and Response
+Table 157 — TPM2_ChangeEPS Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ChangeEPS {NV E}
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPMI_RH_PLATFORM
+
+Description
+
+Table 158 — TPM2_ChangeEPS Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 319
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.5.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+#include "InternalRoutines.h"
+#include "ChangeEPS_fp.h"
+
+TPM_RC
+TPM2_ChangeEPS(
+ChangeEPS_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input parameter is not reference in command action
+in = NULL;
+// Internal Data Update
+// Reset endorsement hierarchy seed from RNG
+CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer);
+// Create new ehProof value from RNG
+CryptGenerateRandom(PROOF_SIZE, gp.ehProof.t.buffer);
+// Enable endorsement hierarchy
+gc.ehEnable = TRUE;
+// set authValue buffer to zeros
+MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size);
+// Set endorsement authValue to null
+gp.endorsementAuth.t.size = 0;
+// Set endorsement authPolicy to null
+gp.endorsementAlg = TPM_ALG_NULL;
+gp.endorsementPolicy.t.size = 0;
+// Flush loaded object in endorsement hierarchy
+ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
+// Flush evict object of endorsement hierarchy stored in NV
+NvFlushHierarchy(TPM_RH_ENDORSEMENT);
+// Save hierarchy changes to NV
+NvWriteReserved(NV_EP_SEED, &gp.EPSeed);
+NvWriteReserved(NV_EH_PROOF, &gp.ehProof);
+NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
+NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
+NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
+// orderly state should be cleared because of the update to state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 320
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+26.6
+
+Part 3: Commands
+
+TPM2_Clear
+
+26.6.1 General Description
+This command removes all TPM context associated with a specific Owner.
+The clear operation will:
+
+
+flush loaded objects (persistent and volatile) in the Storage and Endorsement hierarchies;
+
+
+
+delete any NV Index with TPMA_NV_PLATFORMCREATE == CLEAR;
+
+
+
+change the SPS to a new value from the TPM’s random number generator (RNG),
+
+
+
+change shProof and ehProof,
+NOTE
+
+The proof values may be set from the RNG or derived from the associated new Primary Seed. If
+derived from the Primary Seeds, the derivation of ehProof shall use both the SPS and EPS. The
+computation shall use the SPS as an HMAC key and the derived value may then be a parameter
+in a second HMAC in which the EPS is the HMAC key. The reference design uses values from
+the RNG.
+
+
+
+SET shEnable and ehEnable;
+
+
+
+set ownerAuth, endorsementAuth, and lockoutAuth to the Empty Buffer;
+
+
+
+set ownerPolicy and endorsementPolicy to the Empty Buffer;
+
+
+
+set Clock to zero;
+
+
+
+set resetCount to zero;
+
+
+
+set restartCount to zero; and
+
+
+
+set Safe to YES.
+
+This command requires platformAuth or lockoutAuth. If TPM2_ClearControl() has disabled this command,
+the TPM shall return TPM_RC_DISABLED.
+If this command is authorized using lockoutAuth, the HMAC in the response shall use the new
+lockoutAuth value (that is, the Empty Buffer) when computing response HMAC.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 321
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.6.2 Command and Response
+Table 159 — TPM2_Clear Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Clear {NV E}
+
+@authHandle
+
+TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPMI_RH_CLEAR
+
+Description
+
+Table 160 — TPM2_Clear Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 322
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.6.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Clear_fp.h"
+Error Returns
+TPM_RC_DISABLED
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+Clear command has been disabled
+
+TPM_RC
+TPM2_Clear(
+Clear_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input parameter is not reference in command action
+in = NULL;
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// If Clear command is disabled, return an error
+if(gp.disableClear)
+return TPM_RC_DISABLED;
+// Internal Data Update
+// Reset storage hierarchy seed from RNG
+CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.SPSeed.t.buffer);
+// Create new shProof and ehProof value from RNG
+CryptGenerateRandom(PROOF_SIZE, gp.shProof.t.buffer);
+CryptGenerateRandom(PROOF_SIZE, gp.ehProof.t.buffer);
+// Enable storage and endorsement hierarchy
+gc.shEnable = gc.ehEnable = TRUE;
+// set the authValue buffers to zero
+MemorySet(gp.ownerAuth.t.buffer, 0, gp.ownerAuth.t.size);
+MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size);
+MemorySet(gp.lockoutAuth.t.buffer, 0, gp.lockoutAuth.t.size);
+// Set storage, endorsement and lockout authValue to null
+gp.ownerAuth.t.size = gp.endorsementAuth.t.size = gp.lockoutAuth.t.size = 0;
+// Set storage and endorsement authPolicy to null
+gp.ownerAlg = gp.endorsementAlg = TPM_ALG_NULL;
+gp.ownerPolicy.t.size = gp.endorsementPolicy.t.size = 0;
+// Flush loaded object in storage and endorsement hierarchy
+ObjectFlushHierarchy(TPM_RH_OWNER);
+ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
+// Flush owner and endorsement object and owner index in NV
+NvFlushHierarchy(TPM_RH_OWNER);
+NvFlushHierarchy(TPM_RH_ENDORSEMENT);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 323
+October 31, 2013
+
+ Part 3: Commands
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+
+Trusted Platform Module Library
+
+// Save hierarchy changes to NV
+NvWriteReserved(NV_SP_SEED, &gp.SPSeed);
+NvWriteReserved(NV_SH_PROOF, &gp.shProof);
+NvWriteReserved(NV_EH_PROOF, &gp.ehProof);
+NvWriteReserved(NV_OWNER_AUTH, &gp.ownerAuth);
+NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
+NvWriteReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
+NvWriteReserved(NV_OWNER_ALG, &gp.ownerAlg);
+NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
+NvWriteReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
+NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
+// Initialize dictionary attack parameters
+DAPreInstall_Init();
+// Reset clock
+go.clock = 0;
+go.clockSafe = YES;
+// Update the DRBG state whenever writing orderly state to NV
+CryptDrbgGetPutState(GET_STATE);
+NvWriteReserved(NV_ORDERLY_DATA, &go);
+// Reset counters
+gp.resetCount = gr.restartCount = gr.clearCount = 0;
+gp.auditCounter = 0;
+NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
+NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
+// orderly state should be cleared because of the update to state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 324
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+26.7
+
+Part 3: Commands
+
+TPM2_ClearControl
+
+26.7.1 General Description
+TPM2_ClearControl() disables and enables the execution of TPM2_Clear().
+The TPM will SET the TPM’s TPMA_PERMANENT.disableClear attribute if disable is YES and will
+CLEAR the attribute if disable is NO. When the attribute is SET, TPM2_Clear() may not be executed.
+NOTE
+
+This is to simplify the logic of TPM2_Clear(). TPM2_ClearControl() can be called using platformAuth
+to CLEAR the disableClear attribute and then execute TPM2_Clear().
+
+LockoutAuth may be used to SET disableClear but not to CLEAR it.
+PlatformAuth may be used to SET or CLEAR disableClear.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 325
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.7.2 Command and Response
+Table 161 — TPM2_ClearControl Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ClearControl {NV}
+
+TPMI_RH_CLEAR
+
+@auth
+
+TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPMI_YES_NO
+
+disable
+
+YES if the disableOwnerClear flag is to be SET, NO if
+the flag is to be CLEAR.
+
+Table 162 — TPM2_ClearControl Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 326
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "ClearControl_fp.h"
+Error Returns
+TPM_RC_AUTH_FAIL
+
+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
+33
+
+Meaning
+authorization is not properly given
+
+TPM_RC
+TPM2_ClearControl(
+ClearControl_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE
+if(in->auth == TPM_RH_LOCKOUT && in->disable == NO)
+return TPM_RC_AUTH_FAIL;
+// Internal Data Update
+if(in->disable == YES)
+gp.disableClear = TRUE;
+else
+gp.disableClear = FALSE;
+// Record the change to NV
+NvWriteReserved(NV_DISABLE_CLEAR, &gp.disableClear);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 327
+October 31, 2013
+
+ Part 3: Commands
+
+26.8
+
+Trusted Platform Module Library
+
+TPM2_HierarchyChangeAuth
+
+26.8.1 General Description
+This command allows the authorization secret for a hierarchy or lockout to be changed using the current
+authorization value as the command authorization.
+If authHandle is TPM_RH_PLATFORM, then platformAuth is changed. If authHandle is
+TPM_RH_OWNER, then ownerAuth is changed. If authHandle is TPM_RH_ENDORSEMENT, then
+endorsementAuth is changed. If authHandle is TPM_RH_LOCKOUT, then lockoutAuth is changed.
+If authHandle is TPM_RH_PLATFORM, then Physical Presence may need to be asserted for this
+command to succeed (see 28.2, “TPM2_PP_Commands”).
+The authorization value may be no larger than the digest produced by the hash algorithm used for context
+integrity.
+EXAMPLE
+
+If SHA384 is used in the computation of the integrity values for saved contexts, then the largest
+authorization value is 48 octets.
+
+Page 328
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.8.2 Command and Response
+Table 163 — TPM2_HierarchyChangeAuth Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HierarchyChangeAuth {NV}
+
+TPMI_RH_HIERARCHY_AUTH
+
+@authHandle
+
+TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT,
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_AUTH
+
+newAuth
+
+new authorization value
+
+Table 164 — TPM2_HierarchyChangeAuth Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 329
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.8.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "HierarchyChangeAuth_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+newAuth size is greater than that of integrity hash digest
+
+TPM_RC
+TPM2_HierarchyChangeAuth(
+HierarchyChangeAuth_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Make sure the the auth value is a reasonable size (not larger than
+// the size of the digest produced by the integrity hash. The integrity
+// hash is assumed to produce the longest digest of any hash implemented
+// on the TPM.
+if( MemoryRemoveTrailingZeros(&in->newAuth)
+> CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG))
+return TPM_RC_SIZE + RC_HierarchyChangeAuth_newAuth;
+// Set hierarchy authValue
+switch(in->authHandle)
+{
+case TPM_RH_OWNER:
+gp.ownerAuth = in->newAuth;
+NvWriteReserved(NV_OWNER_AUTH, &gp.ownerAuth);
+break;
+case TPM_RH_ENDORSEMENT:
+gp.endorsementAuth = in->newAuth;
+NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
+break;
+case TPM_RH_PLATFORM:
+gc.platformAuth = in->newAuth;
+// orderly state should be cleared
+g_clearOrderly = TRUE;
+break;
+case TPM_RH_LOCKOUT:
+gp.lockoutAuth = in->newAuth;
+NvWriteReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
+break;
+default:
+pAssert(FALSE);
+break;
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 330
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+27
+
+Part 3: Commands
+
+Dictionary Attack Functions
+
+27.1
+
+Introduction
+
+A TPM is required to have support for logic that will help prevent a dictionary attack on an authorization
+value. The protection is provided by a counter that increments when a password authorization or an
+HMAC authorization fails. When the counter reaches a predefined value, the TPM will not accept, for
+some time interval, further requests that require authorization and the TPM is in Lockout mode. While the
+TPM is in Lockout mode, the TPM will return TPM_RC_LOCKED if the command requires use of an
+object’s or Index’s authValue unless the authorization applies to an entry in the Platform hierarchy.
+NOTE
+
+Authorizations for objects and NV Index values in the Platform hierarchy are never locked out.
+However, a command that requires multiple authorizations will not be accepted when the TPM is in
+Lockout mode unless all of the authorizations reference objects and indexes in the Platform
+hierarchy.
+
+If the TPM is continuously powered for the duration of newRecoveryTime and no authorization failures
+occur, the authorization failure counter will be decremented by one. This property is called “self-healing.”
+Self-healing shall not cause the count of failed attempts to decrement below zero.
+The count of failed attempts, the lockout interval, and self-healing interval are settable using
+TPM2_DictionaryAttackParameters(). The lockout parameters and the current value of the lockout
+counter can be read with TPM2_GetCapability().
+Dictionary attack protection does not apply to an entity associated with a permanent handle (handle type
+== TPM_HT_PERMANENT).
+27.2
+
+TPM2_DictionaryAttackLockReset
+
+27.2.1 General Description
+This command cancels the effect of a TPM lockout due to a number of successive authorization failures.
+If this command is properly authorized, the lockout counter is set to zero.
+Only one authorization failure is allowed for this command during a lockoutRecovery interval (set using
+TPM2_DictionaryAttackParameters().
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 331
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+27.2.2 Command and Response
+Table 165 — TPM2_DictionaryAttackLockReset Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_DictionaryAttackLockReset {NV}
+
+@lockHandle
+
+TPM_RH_LOCKOUT
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_LOCKOUT
+
+Description
+
+Table 166 — TPM2_DictionaryAttackLockReset Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 332
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+27.2.3 Detailed Actions
+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
+
+#include "InternalRoutines.h"
+#include "DictionaryAttackLockReset_fp.h"
+
+TPM_RC
+TPM2_DictionaryAttackLockReset(
+DictionaryAttackLockReset_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input parameter is not reference in command action
+in = NULL;
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+// Set failed tries to 0
+gp.failedTries = 0;
+// Record the changes to NV
+NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 333
+October 31, 2013
+
+ Part 3: Commands
+
+27.3
+
+Trusted Platform Module Library
+
+TPM2_DictionaryAttackParameters
+
+27.3.1 General Description
+This command changes the lockout parameters.
+The command requires lockoutAuth.
+The timeout parameters (newRecoveryTime and lockoutRecovery) indicate values that are measured with
+respect to the Time and not Clock.
+NOTE
+
+Use of Time means that the TPM shall be continuously powered for the duration of a timeout.
+
+If newRecoveryTime is zero, then DA protection is disabled. Authorizations are checked but authorization
+failures will not cause the TPM to enter lockout.
+If newMaxTries is zero, the TPM will be in lockout and use of DA protected entities will be disabled.
+If lockoutRecovery is zero, then the recovery interval is a boot cycle (_TPM_Init followed by
+Startup(CLEAR).
+This command will set the authorization failure count (failedTries) to zero.
+Only one authorization failure is allowed for this command during a lockoutRecovery interval.
+
+Page 334
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+27.3.2 Command and Response
+Table 167 — TPM2_DictionaryAttackParameters Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_DictionaryAttackParameters {NV}
+
+TPMI_RH_LOCKOUT
+
+@lockHandle
+
+TPM_RH_LOCKOUT
+Auth Index: 1
+Auth Role: USER
+
+UINT32
+
+newMaxTries
+
+count of authorization failures before the lockout is
+imposed
+
+UINT32
+
+newRecoveryTime
+
+time in seconds before the authorization failure count
+is automatically decremented
+A value of zero indicates that DA protection is
+disabled.
+
+UINT32
+
+lockoutRecovery
+
+time in seconds after a lockoutAuth failure before use
+of lockoutAuth is allowed
+A value of zero indicates that a reboot is required.
+
+Table 168 — TPM2_DictionaryAttackParameters Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 335
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+27.3.3 Detailed Actions
+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
+33
+
+#include "InternalRoutines.h"
+#include "DictionaryAttackParameters_fp.h"
+
+TPM_RC
+TPM2_DictionaryAttackParameters(
+DictionaryAttackParameters_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+// Set dictionary attack parameters
+gp.maxTries = in->newMaxTries;
+gp.recoveryTime = in->newRecoveryTime;
+gp.lockoutRecovery = in->lockoutRecovery;
+// Set failed tries to 0
+gp.failedTries = 0;
+// Record the changes to NV
+NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
+NvWriteReserved(NV_MAX_TRIES, &gp.maxTries);
+NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime);
+NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery);
+return TPM_RC_SUCCESS;
+}
+
+Page 336
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+28
+
+Part 3: Commands
+
+Miscellaneous Management Functions
+
+28.1
+
+Introduction
+
+This clause contains commands that do not logically group with any other commands.
+28.2
+
+TPM2_PP_Commands
+
+28.2.1 General Description
+This command is used to determine which commands require assertion of Physical Presence (PP) in
+addition to platformAuth/platformPolicy.
+This command requires that auth is TPM_RH_PLATFORM and that Physical Presence be asserted.
+After this command executes successfully, the commands listed in setList will be added to the list of
+commands that require that Physical Presence be asserted when the handle associated with the
+authorization is TPM_RH_PLATFORM. The commands in clearList will no longer require assertion of
+Physical Presence in order to authorize a command.
+If a command is not in either list, its state is not changed. If a command is in both lists, then it will no
+longer require Physical Presence (for example, setList is processed first).
+Only commands with
+handle types of
+TPMI_RH_PLATFORM, TPMI_RH_PROVISION,
+TPMI_RH_CLEAR, or TPMI_RH_HIERARCHY can be gated with Physical Presence. If any other
+command is in either list, it is discarded.
+When a command requires that Physical Presence be provided, then Physical Presence shall be
+asserted for either an HMAC or a Policy authorization.
+NOTE
+
+Physical Presence may be made a requirement of any policy.
+
+TPM2_PP_Commands() always requires assertion of Physical Presence.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 337
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+28.2.2 Command and Response
+Table 169 — TPM2_PP_Commands Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PP_Commands {NV}
+
+TPMI_RH_PLATFORM
+
+@auth
+
+TPM_RH_PLATFORM+PP
+Auth Index: 1
+Auth Role: USER + Physical Presence
+
+TPML_CC
+
+setList
+
+list of commands to be added to those that will require
+that Physical Presence be asserted
+
+TPML_CC
+
+clearList
+
+list of commands that will no longer require that
+Physical Presence be asserted
+
+Table 170 — TPM2_PP_Commands Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 338
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+28.2.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+
+#include "InternalRoutines.h"
+#include "PP_Commands_fp.h"
+
+TPM_RC
+TPM2_PP_Commands(
+PP_Commands_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+TPM_RC
+
+i;
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+// Process set list
+for(i = 0; i < in->setList.count; i++)
+// If command is implemented, set it as PP required. If the input
+// command is not a PP command, it will be ignored at
+// PhysicalPresenceCommandSet().
+if(CommandIsImplemented(in->setList.commandCodes[i]))
+PhysicalPresenceCommandSet(in->setList.commandCodes[i]);
+// Process clear list
+for(i = 0; i < in->clearList.count; i++)
+// If command is implemented, clear it as PP required. If the input
+// command is not a PP command, it will be ignored at
+// PhysicalPresenceCommandClear(). If the input command is
+// TPM2_PP_Commands, it will be ignored as well
+if(CommandIsImplemented(in->clearList.commandCodes[i]))
+PhysicalPresenceCommandClear(in->clearList.commandCodes[i]);
+// Save the change of PP list
+NvWriteReserved(NV_PP_LIST, &gp.ppList);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 339
+October 31, 2013
+
+ Part 3: Commands
+
+28.3
+
+Trusted Platform Module Library
+
+TPM2_SetAlgorithmSet
+
+28.3.1 General Description
+This command allows the platform to change the set of algorithms that are used by the TPM. The
+algorithmSet setting is a vendor-dependent value.
+If the changing of the algorithm set results in a change of the algorithms of PCR banks, then the TPM will
+need to be reset (_TPM_Init and TPM2_Startup(TPM_SU_CLEAR)) before the new PCR settings take
+effect. After this command executes successfully, if startupType in the next TPM2_Startup() is not
+TPM_SU_CLEAR, the TPM shall return TPM_RC_VALUE and enter Failure mode.
+This command does not change the algorithms available to the platform.
+NOTE
+
+The reference implementation does not have support for this command. In particular, it does not
+support use of this command to selectively disable algorithms. Proper support wo uld require
+modification of the unmarshaling code so that each time an algorithm is unmarshaled, it would be
+verified as being enabled.
+
+Page 340
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+28.3.2 Command and Response
+Table 171 — TPM2_SetAlgorithmSet Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SetAlgorithmSet {NV}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM
+Auth Index: 1
+Auth Role: USER
+
+UINT32
+
+algorithmSet
+
+a TPM vendor-dependent value indicating the
+algorithm set selection
+
+Table 172 — TPM2_SetAlgorithmSet Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 341
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+28.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
+#include "InternalRoutines.h"
+#include "SetAlgorithmSet_fp.h"
+
+TPM_RC
+TPM2_SetAlgorithmSet(
+SetAlgorithmSet_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+gp.algorithmSet = in->algorithmSet;
+// Write the algorithm set changes to NV
+NvWriteReserved(NV_ALGORITHM_SET, &gp.algorithmSet);
+return TPM_RC_SUCCESS;
+}
+
+Page 342
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Field Upgrade
+
+29
+29.1
+
+Introduction
+
+This clause contains the commands for managing field upgrade of the firmware in the TPM. The field
+upgrade scheme may be used for replacement or augmentation of the firmware installed in the TPM.
+EXAMPLE 1
+
+If an algorithm is found to be flawed, a patch of that algorithm might be installed using the firmware
+upgrade process. The patch might be a replacement of a portion of the code or a complete
+replacement of the firmware.
+
+EXAMPLE 2
+
+If an additional set of ECC parameters is needed, the firmware process may be used to add the
+parameters to the TPM data set.
+
+The
+field
+upgrade
+process
+uses
+two
+commands
+(TPM2_FieldUpgradeStart()
+and
+TPM2_FieldUpgradeData()). TPM2_FieldUpgradeStart() validates that a signature on the provided digest
+is from the TPM manufacturer and that proper authorization is provided using platformPolicy.
+NOTE 1
+
+The platformPolicy for field upgraded is defined by the PM and may include requirements that the
+upgrade be signed by the PM or the TPM owner and include any other constraints that are desired
+by the PM.
+
+If the proper authorization is given, the TPM will retain the signed digest and enter the Field Upgrade
+mode (FUM). While in FUM, the TPM will accept TPM2_FieldUpgradeData() commands. It may accept
+other commands if it is able to complete them using the previously installed firmware. Otherwise, it will
+return TPM_RC_UPGRADE.
+Each block of the field upgrade shall contain the digest of the next block of the field upgrade data. That
+digest shall be included in the digest of the previous block. The digest of the first block is signed by the
+TPM manufacturer. That signature and first block digest are the parameters for
+TPM2_FieldUpgradeStart(). The digest is saved in the TPM as the required digest for the next field
+upgrade data block and as the identifier of the field upgrade sequence.
+For each field upgrade data block that is sent to the TPM by TPM2_FieldUpgradeData(), the TPM shall
+validate that the digest matches the required digest and if not, shall return TPM_RC_VALUE. The TPM
+shall extract the digest of the next expected block and return that value to the caller, along with the digest
+of the first data block of the update sequence.
+The system may attempt to abandon the firmware upgrade by using a zero-length buffer in
+TPM2_FieldUpdateData(). If the TPM is able to resume operation using the firmware present when the
+upgrade started, then the TPM will indicate that it has abandon the update by setting the digest of the
+next block to the Empty Buffer. If the TPM cannot abandon the update, it will return the expected next
+digest.
+The system may also attempt to abandon the update because of a power interruption. If the TPM is able
+to resume normal operations, then it will respond normally to TPM2_Startup(). If the TPM is not able to
+resume normal operations, then it will respond to any command but TPM2_FieldUpgradeData() with
+TPM_RC_FIELDUPGRADE.
+After a _TPM_Init, system software may not be able to resume the field upgrade that was in process
+when the power interruption occurred. In such case, the TPM firmware may be reset to one of two other
+values:
+
+
+the original firmware that was installed at the factory (“initial firmware”); or
+
+
+
+the firmware that was in the TPM when the field upgrade process started (“previous firmware”).
+
+The TPM retains the digest of the first block for these firmware images and checks to see if the first block
+after _TPM_Init matches either of those digests. If so, the firmware update process restarts and the
+original firmware may be loaded.
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 343
+October 31, 2013
+
+ Part 3: Commands
+NOTE 2
+
+Trusted Platform Module Library
+
+The TPM is required to accept the previous firmware as either a vendor -provided update or as
+recovered from the TPM using TPM2_FirmwareRead().
+
+When the last block of the firmware upgrade is loaded into the TPM (indicated to the TPM by data in the
+data block in a TPM vendor-specific manner), the TPM will complete the upgrade process. If the TPM is
+able to resume normal operations without a reboot, it will set the hash algorithm of the next block to
+TPM_ALG_NULL and return TPM_RC_SUCCESS. If a reboot is required, the TPM shall return
+TPM_RC_REBOOT in response to the last TPM2_FieldUpgradeData() and all subsequent TPM
+commands until a _TPM_Init is received.
+NOTE 3
+
+Because no additional data is allowed when the res ponse code is not TPM_RC_SUCCESS, the TPM
+returns TPM_RC_SUCCESS for all calls to TPM2_FieldUpgradeData() except the last. In this
+manner, the TPM is able to indicate the digest of the next block. If a _TPM_Init occurs while the
+TPM is in FUM, the next block may be the digest for the first block of the original firmware. If it is
+not, then the TPM will not accept the original firmware until the next _TPM_Init when the TPM is in
+FUM.
+
+During the field upgrade process, the TPM shall preserve:
+
+
+Primary Seeds;
+
+
+
+Hierarchy authValue, authPolicy, and proof values;
+
+
+
+Lockout authValue and authorization failure count values;
+
+
+
+PCR authValue and authPolicy values;
+
+
+
+NV Index allocations and contents;
+
+
+
+Persistent object allocations and contents; and
+
+
+
+Clock.
+
+Page 344
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+29.2
+
+Part 3: Commands
+
+TPM2_FieldUpgradeStart
+
+29.2.1 General Description
+This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a Field Upgrade
+Manifest.
+If the signature checks
+TPM2_FieldUpgradeData().
+
+succeed,
+
+the
+
+authorization
+
+is
+
+valid
+
+and
+
+the
+
+TPM
+
+will
+
+accept
+
+This signature is checked against the loaded key referenced by keyHandle. This key will have a Name
+that is the same as a value that is part of the TPM firmware data. If the signature is not valid, the TPM
+shall return TPM_RC_SIGNATURE.
+NOTE
+
+A loaded key is used rather than a hard-coded key to reduce the amount of memory needed for this
+key data in case more than one vendor key is needed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 345
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+29.2.2 Command and Response
+Table 173 — TPM2_FieldUpgradeStart Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_FieldUpgradeStart
+
+TPMI_RH_PLATFORM
+
+@authorization
+
+TPM_RH_PLATFORM+{PP}
+Auth Index:1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+handle of a public area that contains the TPM Vendor
+Authorization Key that will be used to validate
+manifestSignature
+Auth Index: None
+
+TPM2B_DIGEST
+
+fuDigest
+
+digest of the first block in the field upgrade sequence
+
+TPMT_SIGNATURE
+
+manifestSignature
+
+signature over fuDigest using the key associated with
+keyHandle (not optional)
+
+Table 174 — TPM2_FieldUpgradeStart Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 346
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+29.2.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+#include "InternalRoutines.h"
+#include "FieldUpgradeStart_fp.h"
+#if CC_FieldUpgradeStart == YES
+
+TPM_RC
+TPM2_FieldUpgradeStart(
+FieldUpgradeStart_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+// Not implemented
+UNUSED_PARAMETER(in);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 347
+October 31, 2013
+
+ Part 3: Commands
+
+29.3
+
+Trusted Platform Module Library
+
+TPM2_FieldUpgradeData
+
+29.3.1 General Description
+This command will take the actual field upgrade image to be installed on the TPM. The exact format of
+fuData is vendor-specific. This command is only possible following a successful
+TPM2_FieldUpgradeStart().
+If
+the
+TPM
+has
+not
+received
+a
+properly
+authorized
+TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE.
+The TPM will validate that the digest of fuData matches an expected value. If so, the TPM may buffer or
+immediately apply the update. If the digest of fuData does not match an expected value, the TPM shall
+return TPM_RC_VALUE.
+
+Page 348
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+29.3.2 Command and Response
+Table 175 — TPM2_FieldUpgradeData Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_FieldUpgradeData {NV}
+
+TPM2B_MAX_BUFFER
+
+fuData
+
+field upgrade image data
+
+Table 176 — TPM2_FieldUpgradeData Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMT_HA+
+
+nextDigest
+
+tagged digest of the next block
+TPM_ALG_NULL if field update is complete
+
+TPMT_HA
+
+firstDigest
+
+tagged digest of the first block of the sequence
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 349
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+29.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+
+#include "InternalRoutines.h"
+#include "FieldUpgradeData_fp.h"
+#if CC_FieldUpgradeData == YES
+
+TPM_RC
+TPM2_FieldUpgradeData(
+FieldUpgradeData_In
+FieldUpgradeData_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Not implemented
+UNUSED_PARAMETER(in);
+UNUSED_PARAMETER(out);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 350
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+29.4
+
+Part 3: Commands
+
+TPM2_FirmwareRead
+
+29.4.1 General Description
+This command is used to read a copy of the current firmware installed in the TPM.
+The presumption is that the data will be returned in reverse order so that the last block in the sequence
+would be the first block given to the TPM in case of a failure recovery. If the TPM2_FirmwareRead
+sequence completes successfully, then the data provided from the TPM will be sufficient to allow the TPM
+to recover from an abandoned upgrade of this firmware.
+To start the sequence of retrieving the data, the caller sets sequenceNumber to zero. When the TPM has
+returned all the firmware data, the TPM will return the Empty Buffer as fuData.
+The contents of fuData are opaque to the caller.
+NOTE 1
+
+The caller should retain the ordering of the update blocks so that the blocks sent to the TPM have
+the same size and inverse order as the blocks returned by a sequence of calls to this command.
+
+NOTE 2
+
+Support for this command is optional even if the TPM implements TPM2_FieldUpgradeStart() and
+TPM2_FieldUpgradeData().
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 351
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+29.4.2 Command and Response
+Table 177 — TPM2_FirmwareRead Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_FirmwareRead
+
+UINT32
+
+sequenceNumber
+
+the number of previous calls to this command in this
+sequence
+set to 0 on the first call
+
+Table 178 — TPM2_FirmwareRead Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_BUFFER
+
+fuData
+
+Page 352
+October 31, 2013
+
+field upgrade image data
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+29.4.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+#include "InternalRoutines.h"
+#include "FirmwareRead_fp.h"
+
+TPM_RC
+TPM2_FirmwareRead(
+FirmwareRead_In
+FirmwareRead_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Not implemented
+UNUSED_PARAMETER(in);
+UNUSED_PARAMETER(out);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 353
+October 31, 2013
+
+ Part 3: Commands
+
+30
+
+Trusted Platform Module Library
+
+Context Management
+
+30.1
+
+Introduction
+
+Three of the commands in this clause (TPM2_ContextSave(), TPM2_ContextLoad(), and
+TPM2_FlushContext()) implement the resource management described in the "Context Management"
+clause in Part 1.
+The fourth command in this clause (TPM2_EvictControl()) is used to control the persistence of a loadable
+objects in TPM memory. Background for this command may be found in the "Owner and Platform Evict
+Objects" clause in Part 1.
+30.2
+
+TPM2_ContextSave
+
+30.2.1 General Description
+This command saves a session context, object context, or sequence object context outside the TPM.
+No authorization sessions of any type are allowed with this command and tag is required to be
+TPM_ST_NO_SESSIONS.
+NOTE
+
+This preclusion avoids complex issues of dealing with the same session in handle and in the session
+area. While it might be possible to provide specificity, it would add unnecessary complexity to the
+TPM and, because this capability would provide no application benefit, use of authorization ses sions
+for audit or encryption is prohibited.
+
+The TPM shall encrypt and integrity protect the context as described in the "Context Protection" clause in
+Part 1.
+See the “Context Data” clause in Part 2 for a description of the context structure in the response.
+
+Page 354
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.2.2 Command and Response
+Table 179 — TPM2_ContextSave Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ContextSave
+
+TPMI_DH_CONTEXT
+
+saveHandle
+
+handle of the resource to save
+Auth Index: None
+
+Table 180 — TPM2_ContextSave Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMS_CONTEXT
+
+context
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 355
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ContextSave_fp.h"
+#include "Context_spt_fp.h"
+Error Returns
+TPM_RC_CONTEXT_GAP
+
+a contextID could not be assigned for a session context save
+
+TPM_RC_TOO_MANY_CONTEXTS
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+no more contexts can be saved as the counter has maxed out
+
+TPM_RC
+TPM2_ContextSave(
+ContextSave_In
+ContextSave_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+UINT16
+// blob.
+UINT64
+TPM2B_SYM_KEY
+TPM2B_IV
+
+result;
+fingerprintSize;
+
+TPM2B_DIGEST
+UINT16
+BYTE
+
+integrity;
+integritySize;
+*buffer;
+
+contextID = 0;
+symKey;
+iv;
+
+// The size of fingerprint in context
+// session context ID
+
+// This command may cause the orderlyState to be cleared due to
+// the update of state reset data. If this is the case, check if NV is
+// available first
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+}
+// Internal Data Update
+// Initialize output handle. At the end of command action, the output
+// handle of an object will be replaced, while the output handle
+// for a session will be the same as input
+out->context.savedHandle = in->saveHandle;
+// Get the size of fingerprint in context blob. The sequence value in
+// TPMS_CONTEXT structure is used as the fingerprint
+fingerprintSize = sizeof(out->context.sequence);
+// Compute the integrity size at the beginning of context blob
+integritySize = sizeof(integrity.t.size)
++ CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
+// Perform object or session specific context save
+switch(HandleGetType(in->saveHandle))
+{
+case TPM_HT_TRANSIENT:
+{
+
+Page 356
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+
+OBJECT
+OBJECT
+
+Part 3: Commands
+
+*object = ObjectGet(in->saveHandle);
+*outObject =
+(OBJECT *)(out->context.contextBlob.t.buffer
++ integritySize + fingerprintSize);
+
+// Set size of the context data. The contents of context blob is vendor
+// defined. In this implementation, the size is size of integrity
+// plus fingerprint plus the whole internal OBJECT structure
+out->context.contextBlob.t.size = integritySize +
+fingerprintSize + sizeof(*object);
+// Copy the whole internal OBJECT structure to context blob, leave
+// the size for fingerprint
+*outObject = *object;
+// Increment object context ID
+gr.objectContextID++;
+// If object context ID overflows, TPM should be put in failure mode
+if(gr.objectContextID == 0)
+FAIL(FATAL_ERROR_INTERNAL);
+// Fill in other return values for an object.
+out->context.sequence = gr.objectContextID;
+// For regular object, savedHandle is 0x80000000. For sequence object,
+// savedHandle is 0x80000001. For object with stClear, savedHandle
+// is 0x80000002
+if(ObjectIsSequence(object))
+{
+out->context.savedHandle = 0x80000001;
+SequenceDataImportExport(object, outObject, EXPORT_STATE);
+}
+else if(object->attributes.stClear == SET)
+{
+out->context.savedHandle = 0x80000002;
+}
+else
+{
+out->context.savedHandle = 0x80000000;
+}
+// Get object hierarchy
+out->context.hierarchy = ObjectDataGetHierarchy(object);
+break;
+}
+case TPM_HT_HMAC_SESSION:
+case TPM_HT_POLICY_SESSION:
+{
+SESSION
+*session = SessionGet(in->saveHandle);
+// Set size of the context data. The contents of context blob is vendor
+// defined. In this implementation, the size of context blob is the
+// size of a internal session structure plus the size of
+// fingerprint plus the size of integrity
+out->context.contextBlob.t.size = integritySize +
+fingerprintSize + sizeof(*session);
+// Copy the whole internal SESSION structure to context blob.
+// Save space for fingerprint at the beginning of the buffer
+// This is done before anything else so that the actual context
+// can be reclaimed after this call
+MemoryCopy(out->context.contextBlob.t.buffer
++ integritySize + fingerprintSize,
+session, sizeof(*session),
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 357
+October 31, 2013
+
+ Part 3: Commands
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+
+Trusted Platform Module Library
+sizeof(out->context.contextBlob.t.buffer)
+- integritySize - fingerprintSize);
+
+// Fill in the other return parameters for a session
+// Get a context ID and set the session tracking values appropriately
+// TPM_RC_CONTEXT_GAP is a possible error.
+// SessionContextSave() will flush the in-memory context
+// so no additional errors may occur after this call.
+result = SessionContextSave(out->context.savedHandle, &contextID);
+if(result != TPM_RC_SUCCESS) return result;
+// sequence number is the current session contextID
+out->context.sequence = contextID;
+// use TPM_RH_NULL as hierarchy for session context
+out->context.hierarchy = TPM_RH_NULL;
+break;
+}
+default:
+// SaveContext may only take an object handle or a session handle.
+// All the other handle type should be filtered out at unmarshal
+pAssert(FALSE);
+break;
+}
+// Save fingerprint at the beginning of encrypted area of context blob.
+// Reserve the integrity space
+MemoryCopy(out->context.contextBlob.t.buffer + integritySize,
+&out->context.sequence, sizeof(out->context.sequence),
+sizeof(out->context.contextBlob.t.buffer) - integritySize);
+// Compute context encryption key
+ComputeContextProtectionKey(&out->context, &symKey, &iv);
+// Encrypt context blob
+CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize,
+CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
+TPM_ALG_CFB, symKey.t.buffer, &iv,
+out->context.contextBlob.t.size - integritySize,
+out->context.contextBlob.t.buffer + integritySize);
+// Compute integrity hash for the object
+// In this implementation, the same routine is used for both sessions
+// and objects.
+ComputeContextIntegrity(&out->context, &integrity);
+// add integrity at the beginning of context blob
+buffer = out->context.contextBlob.t.buffer;
+TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
+// orderly state should be cleared because of the update of state reset and
+// state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 358
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+30.3
+
+Part 3: Commands
+
+TPM2_ContextLoad
+
+30.3.1 General Description
+This command is used to reload a context that has been saved by TPM2_ContextSave().
+No authorization sessions of any type are allowed with this command and tag is required to be
+TPM_ST_NO_SESSIONS (see note in 30.2.1).
+The TPM will return TPM_RC_HIERARCHY if the context is associated with a hierarchy that is disabled.
+NOTE
+
+Contexts for authorization sessions and for sequence object s belong to the NULL hierarchy which is
+never disabled.
+
+See the “Context Data” clause in Part 2 for a description of the values in the context parameter.
+If the integrity HMAC of the saved context is not valid, the TPM shall return TPM_RC_INTEGRITY.
+The TPM shall perform a check on the decrypted context as described in the "Context Confidentiality
+Protections" clause of Part 1 and enter failure mode if the check fails.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 359
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.3.2 Command and Response
+Table 181 — TPM2_ContextLoad Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ContextLoad
+
+TPMS_CONTEXT
+
+context
+
+the context blob
+
+Table 182 — TPM2_ContextLoad Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_DH_CONTEXT
+
+loadedHandle
+
+Page 360
+October 31, 2013
+
+the handle assigned to the resource after it has been
+successfully loaded
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ContextLoad_fp.h"
+#include "Context_spt_fp.h"
+Error Returns
+TPM_RC_CONTEXT_GAP
+
+there is only one available slot and this is not the oldest saved
+session context
+
+TPM_RC_HANDLE
+
+'context. savedHandle' does not reference a saved session
+
+TPM_RC_HIERARCHY
+
+'context.hierarchy' is disabled
+
+TPM_RC_INTEGRITY
+
+context integrity check fail
+
+TPM_RC_OBJECT_MEMORY
+
+no free slot for an object
+
+TPM_RC_SESSION_MEMORY
+
+no free session slots
+
+TPM_RC_SIZE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
+Meaning
+
+incorrect context blob size
+
+TPM_RC
+TPM2_ContextLoad(
+ContextLoad_In
+ContextLoad_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Local Variables
+TPM_RC
+result = TPM_RC_SUCCESS;
+TPM2B_DIGEST
+TPM2B_DIGEST
+UINT16
+UINT64
+BYTE
+INT32
+
+ingerityToCompare;
+integrity;
+integritySize;
+fingerprint;
+*buffer;
+size;
+
+TPM_HT
+TPM2B_SYM_KEY
+TPM2B_IV
+
+handleType;
+symKey;
+iv;
+
+// Input Validation
+// Check context blob size
+handleType = HandleGetType(in->context.savedHandle);
+// Check integrity
+// In this implementation, the same routine is used for both sessions
+// and objects.
+integritySize = sizeof(integrity.t.size)
++ CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
+// Get integrity from context blob
+buffer = in->context.contextBlob.t.buffer;
+size = (INT32) in->context.contextBlob.t.size;
+result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Compute context integrity
+ComputeContextIntegrity(&in->context, &ingerityToCompare);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 361
+October 31, 2013
+
+ Part 3: Commands
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
+Trusted Platform Module Library
+
+// Compare integrity
+if(!Memory2BEqual(&integrity.b, &ingerityToCompare.b))
+return TPM_RC_INTEGRITY + RC_ContextLoad_context;
+// Compute context encryption key
+ComputeContextProtectionKey(&in->context, &symKey, &iv);
+// Decrypt context data in place
+CryptSymmetricDecrypt(in->context.contextBlob.t.buffer + integritySize,
+CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
+TPM_ALG_CFB, symKey.t.buffer, &iv,
+in->context.contextBlob.t.size - integritySize,
+in->context.contextBlob.t.buffer + integritySize);
+// Read the fingerprint value, skip the leading integrity size
+MemoryCopy(&fingerprint, in->context.contextBlob.t.buffer + integritySize,
+sizeof(fingerprint), sizeof(fingerprint));
+// Check fingerprint. If the check fails, TPM should be put to failure mode
+if(fingerprint != in->context.sequence)
+FAIL(FATAL_ERROR_INTERNAL);
+// Perform object or session specific input check
+switch(handleType)
+{
+case TPM_HT_TRANSIENT:
+{
+// Get a pointer to the object in the context blob
+OBJECT
+*outObject = (OBJECT *)(in->context.contextBlob.t.buffer
++ integritySize + sizeof(fingerprint));
+// Discard any changes to the handle that the TRM might have made
+in->context.savedHandle = TRANSIENT_FIRST;
+// If hierarchy is disabled, no object context can be loaded in this
+// hierarchy
+if(!HierarchyIsEnabled(in->context.hierarchy))
+return TPM_RC_HIERARCHY + RC_ContextLoad_context;
+// Restore object. A TPM_RC_OBJECT_MEMORY error may be returned at
+// this point
+result = ObjectContextLoad(outObject, &out->loadedHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+// If this is a sequence object, the crypto library may need to
+// reformat the data into an internal format
+if(ObjectIsSequence(outObject))
+SequenceDataImportExport(ObjectGet(out->loadedHandle),
+outObject, IMPORT_STATE);
+break;
+}
+case TPM_HT_POLICY_SESSION:
+case TPM_HT_HMAC_SESSION:
+{
+SESSION
+
+*session = (SESSION *)(in->context.contextBlob.t.buffer
++ integritySize + sizeof(fingerprint));
+
+// This command may cause the orderlyState to be cleared due to
+// the update of state reset data. If this is the case, check if NV is
+// available first
+
+Page 362
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+
+Part 3: Commands
+
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned
+// at this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Check if input handle points to a valid saved session
+if(!SessionIsSaved(in->context.savedHandle))
+return TPM_RC_HANDLE + RC_ContextLoad_context;
+// Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
+// may be returned at this point
+result = SessionContextLoad(session, &in->context.savedHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+out->loadedHandle = in->context.savedHandle;
+// orderly state should be cleared because of the update of state
+// reset and state clear data
+g_clearOrderly = TRUE;
+break;
+}
+default:
+// Context blob may only have an object handle or a session handle.
+// All the other handle type should be filtered out at unmarshal
+pAssert(FALSE);
+break;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 363
+October 31, 2013
+
+ Part 3: Commands
+
+30.4
+
+Trusted Platform Module Library
+
+TPM2_FlushContext
+
+30.4.1 General Description
+This command causes all context associated with a loaded object or session to be removed from TPM
+memory.
+This command may not be used to remove a persistent object from the TPM.
+A session does not have to be loaded in TPM memory to have its context flushed. The saved session
+context associated with the indicated handle is invalidated.
+No sessions of any type are allowed with
+TPM_ST_NO_SESSIONS (see note in 30.2.1).
+
+this
+
+command
+
+and
+
+tag
+
+is
+
+required
+
+to
+
+be
+
+If the handle is for a transient object and the handle is not associated with a loaded object, then the TPM
+shall return TPM_RC_HANDLE.
+If the handle is for an authorization session and the handle does not reference a loaded or active session,
+then the TPM shall return TPM_RC_HANDLE.
+NOTE
+
+flushHandle is a parameter and not a handle. If it were in the handle area, the TPM would validate
+that the context for the referenced entity is in the TPM. When a TPM2_FlushContext references a
+saved session context, it is not necessary for the context to be in the TPM .
+
+Page 364
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.4.2 Command and Response
+Table 183 — TPM2_FlushContext Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPMI_DH_CONTEXT
+
+flushHandle
+
+TPM_CC_FlushContext
+the handle of the item to flush
+NOTE
+
+This is a use of a handle as a parameter.
+
+Table 184 — TPM2_FlushContext Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 365
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "FlushContext_fp.h"
+Error Returns
+TPM_RC_HANDLE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
+Meaning
+flushHandle does not reference a loaded object or session
+
+TPM_RC
+TPM2_FlushContext(
+FlushContext_In
+)
+{
+// Internal Data Update
+
+*in
+
+// IN: input parameter list
+
+// Call object or session specific routine to flush
+switch(HandleGetType(in->flushHandle))
+{
+case TPM_HT_TRANSIENT:
+if(!ObjectIsPresent(in->flushHandle))
+return TPM_RC_HANDLE;
+// Flush object
+ObjectFlush(in->flushHandle);
+break;
+case TPM_HT_HMAC_SESSION:
+case TPM_HT_POLICY_SESSION:
+if(
+!SessionIsLoaded(in->flushHandle)
+&& !SessionIsSaved(in->flushHandle)
+)
+return TPM_RC_HANDLE;
+// If the session to be flushed is the exclusive audit session, then
+// indicate that there is no exclusive audit session any longer.
+if(in->flushHandle == g_exclusiveAuditSession)
+g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
+// Flush session
+SessionFlush(in->flushHandle);
+break;
+default:
+// This command only take object or session handle.
+// should be filtered out at handle unmarshal
+pAssert(FALSE);
+break;
+}
+
+Other handles
+
+return TPM_RC_SUCCESS;
+}
+
+Page 366
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+30.5
+
+Part 3: Commands
+
+TPM2_EvictControl
+
+30.5.1 General Description
+This command allows a transient object to be made persistent or a persistent object to be evicted.
+NOTE 1
+
+A transient object is one that may be removed from TPM memory using either TPM2_FlushContext
+or TPM2_Startup(). A persistent object is not removed from TPM memory by TPM2_FlushContext()
+or TPM2_Startup().
+
+If objectHandle is a transient object, then the call is to make the object persistent and assign
+persistentHandle to the persistent version of the object. If objectHandle is a persistent object, then the call
+is to evict the persistent object.
+Before execution of TPM2_EvictControl code below, the TPM verifies that objectHandle references an
+object that is resident on the TPM and that persistentHandle is a valid handle for a persistent object.
+NOTE 2
+
+This requirement simplifies the unmarshaling code so that it only need check that persistentHandle
+is always a persistent object.
+
+If objectHandle references a transient object:
+a) The TPM shall return TPM_RC_ATTRIBUTES if
+1) it is in the hierarchy of TPM_RH_NULL,
+2) only the public portion of the object is loaded, or
+3) the stClear is SET in the object or in an ancestor key.
+b) The TPM shall return TPM_RC_HIERARCHY if the object is not in the proper hierarchy as
+determined by auth.
+1) If auth is TPM_RH_PLATFORM, the proper hierarchy is the Platform hierarchy.
+2) If auth is TPM_RH_OWNER, the proper hierarchy is either the Storage or the Endorsement
+hierarchy.
+c) The TPM shall return TPM_RC_RANGE if persistentHandle is not in the proper range as determined
+by auth.
+1) If auth is TPM_RH_OWNER, then persistentHandle shall be in the inclusive range of
+81 00 00 0016 to 81 7F FF FF16.
+2) If auth is TPM_RH_PLATFORM, then persistentHandle shall be in the inclusive range of
+81 80 00 0016 to 81 FF FF FF16.
+d) The TPM shall return TPM_RC_NV_DEFINED if a persistent object exists with the same handle as
+persistentHandle.
+e) The TPM shall return TPM_RC_NV_SPACE if insufficient space is available to make the object
+persistent.
+f)
+
+The TPM shall return TPM_RC_NV_SPACE if execution of this command will prevent the TPM from
+being able to hold two transient objects of any kind.
+NOTE 3
+
+This requirement anticipates that a TPM may be implemented such that all TPM memory is non volatile and not subject to endurance issues. In such case, there is no movement of an object
+between memory of different types and it is necessary that the TPM ensure that it is always
+possible for the management software to move objects to/from TPM memory in order to ensure
+that the objects required for command execution can be context restored.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 367
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+g) If the TPM returns TPM_RC_SUCCESS, the object referenced by objectHandle will not be flushed
+and both objectHandle and persistentHandle may be used to access the object.
+If objectHandle references a persistent object:
+h) The TPM shall return TPM_RC_RANGE if objectHandle is not in the proper range as determined by
+auth. If auth is TPM_RC_OWNER, objectHandle shall be in the inclusive range of 81 00 00 0016 to
+81 7F FF FF16. If auth is TPM_RC_PLATFORM, objectHandle may be any valid persistent object
+handle.
+i)
+
+If the TPM returns TPM_RC_SUCCESS, objectHandle will be removed from persistent memory and
+no longer be accessible.
+
+NOTE 4
+
+The persistent object is not converted to a transient object, as this would prevent the immediate
+revocation of an object by removing it from persistent memory.
+
+Page 368
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.5.2 Command and Response
+Table 185 — TPM2_EvictControl Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EvictControl {NV}
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+objectHandle
+
+the handle of a loaded object
+Auth Index: None
+
+persistentHandle
+
+if objectHandle is a transient object handle, then this is
+the persistent handle for the object
+if objectHandle is a persistent object handle, then this
+shall be the same value as persistentHandle
+
+TPMI_DH_PERSISTENT
+
+Description
+
+Table 186 — TPM2_EvictControl Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 369
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.5.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "EvictControl_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+an object with temporary, stClear or publicOnly attribute SET cannot
+be made persistent
+
+TPM_RC_HIERARCHY
+
+auth cannot authorize the operation in the hierarchy of evictObject
+
+TPM_RC_HANDLE
+
+evictHandle of the persistent object to be evicted is not the same as
+the persistentHandle argument
+
+TPM_RC_NV_HANDLE
+
+persistentHandle is unavailable
+
+TPM_RC_NV_SPACE
+
+no space in NV to make evictHandle persistent
+
+TPM_RC_RANGE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
+Meaning
+
+persistentHandle is not in the range corresponding to the hierarchy of
+evictObject
+
+TPM_RC
+TPM2_EvictControl(
+EvictControl_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+OBJECT
+
+result;
+*evictObject;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// Get internal object pointer
+evictObject = ObjectGet(in->objectHandle);
+// Temporary, stClear or public only objects can not be made persistent
+if(
+evictObject->attributes.temporary == SET
+|| evictObject->attributes.stClear == SET
+|| evictObject->attributes.publicOnly == SET
+)
+return TPM_RC_ATTRIBUTES + RC_EvictControl_objectHandle;
+// If objectHandle refers to a persistent object, it should be the same as
+// input persistentHandle
+if(
+evictObject->attributes.evict == SET
+&& evictObject->evictHandle != in->persistentHandle
+)
+return TPM_RC_HANDLE + RC_EvictControl_objectHandle;
+// Additional auth validation
+if(in->auth == TPM_RH_PLATFORM)
+{
+// To make persistent
+if(evictObject->attributes.evict == CLEAR)
+{
+// Platform auth can not set evict object in storage or endorsement
+// hierarchy
+
+Page 370
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+
+Part 3: Commands
+
+if(evictObject->attributes.ppsHierarchy == CLEAR)
+return TPM_RC_HIERARCHY + RC_EvictControl_objectHandle;
+// Platform cannot use a handle outside of platform persistent range.
+if(!NvIsPlatformPersistentHandle(in->persistentHandle))
+return TPM_RC_RANGE + RC_EvictControl_persistentHandle;
+}
+// Platform auth can delete any persistent object
+}
+else if(in->auth == TPM_RH_OWNER)
+{
+// Owner auth can not set or clear evict object in platform hierarchy
+if(evictObject->attributes.ppsHierarchy == SET)
+return TPM_RC_HIERARCHY + RC_EvictControl_objectHandle;
+// Owner cannot use a handle outside of owner persistent range.
+if(
+evictObject->attributes.evict == CLEAR
+&& !NvIsOwnerPersistentHandle(in->persistentHandle)
+)
+return TPM_RC_RANGE + RC_EvictControl_persistentHandle;
+}
+else
+{
+// Other auth is not allowed in this command and should be filtered out
+// at unmarshal process
+pAssert(FALSE);
+}
+// Internal Data Update
+// Change evict state
+if(evictObject->attributes.evict == CLEAR)
+{
+// Make object persistent
+// A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this
+// point
+result = NvAddEvictObject(in->persistentHandle, evictObject);
+if(result != TPM_RC_SUCCESS) return result;
+}
+else
+{
+// Delete the persistent object in NV
+NvDeleteEntity(evictObject->evictHandle);
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 371
+October 31, 2013
+
+ Part 3: Commands
+
+31
+
+Trusted Platform Module Library
+
+Clocks and Timers
+
+31.1
+
+TPM2_ReadClock
+
+31.1.1 General Description
+This command reads the current TPMS_TIME_INFO structure that contains the current setting of Time,
+Clock, resetCount, and restartCount.
+No authorization sessions of any type are allowed with this command and tag is required to be
+TPM_ST_NO_SESSIONS.
+NOTE
+
+This command is intended to allow the TCB to have access to values that have the potential to be
+privacy sensitive. The values may be read without authorization because the TCB will not disclose
+these values. Since they are not signed and cannot be accessed in a command that uses an
+authorization session, it is not possible for any entity, other than the TCB, to be assured that the
+values are accurate.
+
+Page 372
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+31.1.2 Command and Response
+Table 187 — TPM2_ReadClock Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ReadClock
+
+Table 188 — TPM2_ReadClock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+returnCode
+
+TPMS_TIME_INFO
+
+currentTime
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 373
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+31.1.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+#include "InternalRoutines.h"
+#include "ReadClock_fp.h"
+
+TPM_RC
+TPM2_ReadClock(
+ReadClock_Out *out
+)
+{
+// Command Output
+
+// OUT: output parameter list
+
+out->currentTime.time = g_time;
+TimeFillInfo(&out->currentTime.clockInfo);
+return TPM_RC_SUCCESS;
+}
+
+Page 374
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+31.2
+
+Part 3: Commands
+
+TPM2_ClockSet
+
+31.2.1 General Description
+This command is used to advance the value of the TPM’s Clock. The command will fail if newTime is less
+than the current value of Clock or if the new time is greater than FF FF 00 00 00 00 00 0016. If both of
+these checks succeed, Clock is set to newTime. If either of these checks fails, the TPM shall return
+TPM_RC_VALUE and make no change to Clock.
+NOTE
+
+This maximum setting would prevent Clock from rolling over to zero for approximately 8,000 years if
+the Clock update rate was set so that TPM time was passing 33 percent faster than real time. This
+would still be more than 6,000 years before Clock would roll over to zero. Because Clock will not roll
+over in the lifetime of the TPM, there is no need for external software to deal with the possibility that
+Clock may wrap around.
+
+If the value of Clock after the update makes the volatile and non-volatile versions of
+TPMS_CLOCK_INFO.clock differ by more than the reported update interval, then the TPM shall update
+the non-volatile version of TPMS_CLOCK_INFO.clock before returning.
+This command requires platformAuth or ownerAuth.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 375
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+31.2.2 Command and Response
+Table 189 — TPM2_ClockSet Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ClockSet {NV}
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+UINT64
+
+newTime
+
+new Clock setting in milliseconds
+
+Table 190 — TPM2_ClockSet Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+returnCode
+
+Page 376
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+31.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "ClockSet_fp.h"
+
+Read the current TPMS_TIMER_INFO structure settings
+Error Returns
+TPM_RC_VALUE
+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
+33
+34
+35
+
+Meaning
+invalid new clock
+
+TPM_RC
+TPM2_ClockSet(
+ClockSet_In *in
+)
+{
+#define CLOCK_UPDATE_MASK
+UINT64
+clockNow;
+
+// IN: input parameter list
+((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
+
+// Input Validation
+// new time can not be bigger than 0xFFFF000000000000 or smaller than
+// current clock
+if(in->newTime > 0xFFFF000000000000ULL
+|| in->newTime < go.clock)
+return TPM_RC_VALUE + RC_ClockSet_newTime;
+// Internal Data Update
+// Internal Data Update
+clockNow = go.clock;
+// grab the old value
+go.clock = in->newTime;
+// set the new value
+// Check to see if the update has caused a need for an nvClock update
+if((in->newTime & CLOCK_UPDATE_MASK) > (clockNow & CLOCK_UPDATE_MASK))
+{
+CryptDrbgGetPutState(GET_STATE);
+NvWriteReserved(NV_ORDERLY_DATA, &go);
+// Now the time state is safe
+go.clockSafe = YES;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 377
+October 31, 2013
+
+ Part 3: Commands
+
+31.3
+
+Trusted Platform Module Library
+
+TPM2_ClockRateAdjust
+
+31.3.1 General Description
+This command adjusts the rate of advance of Clock and Time to provide a better approximation to real
+time.
+The rateAdjust value is relative to the current rate and not the nominal rate of advance.
+EXAMPLE 1
+
+If this command had been called three times with rateAdjust = TPM_CLOCK_COARSE_SLOWER
+and once with rateAdjust = TPM_CLOCK_COARSE_FASTER, the net effect will be as if the
+command had been called twice with rateAdjust = TPM_CLOCK_COARSE_SLOWER.
+
+The range of adjustment shall be sufficient to allow Clock and Time to advance at real time but no more.
+If the requested adjustment would make the rate advance faster or slower than the nominal accuracy of
+the input frequency, the TPM shall return TPM_RC_VALUE.
+EXAMPLE 2
+
+If the frequency tolerance of the TPM's input clock is +/-10 percent, then the TPM will return
+TPM_RC_VALUE if the adjustment would make Clock run more than 10 percent faster or slower than
+nominal. That is, if the input oscillator were nominally 100 megahertz (MHz), then 1 millisecond (ms)
+would normally take 100,000 counts. The update Clock should be adjustable so that 1 ms is between
+90,000 and 110,000 counts.
+
+The interpretation of “fine” and “coarse” adjustments is implementation-specific.
+The nominal rate of advance for Clock and Time shall be accurate to within 15 percent. That is, with no
+adjustment applied, Clock and Time shall be advanced at a rate within 15 percent of actual time.
+NOTE
+
+If the adjustments are incorrect, it will be possible to m ake the difference between advance of
+Clock/Time and real time to be as much as 1.15 2 or ~1.33.
+
+Changes to the current Clock update rate adjustment need not be persisted across TPM power cycles.
+
+Page 378
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+31.3.2 Command and Response
+Table 191 — TPM2_ClockRateAdjust Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ClockRateAdjust
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPM_CLOCK_ADJUST
+
+rateAdjust
+
+Adjustment to current Clock update rate
+
+Table 192 — TPM2_ClockRateAdjust Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+returnCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 379
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+31.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+#include "InternalRoutines.h"
+#include "ClockRateAdjust_fp.h"
+
+TPM_RC
+TPM2_ClockRateAdjust(
+ClockRateAdjust_In
+*in
+)
+{
+// Internal Data Update
+TimeSetAdjustRate(in->rateAdjust);
+
+// IN: input parameter list
+
+return TPM_RC_SUCCESS;
+}
+
+Page 380
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+32
+
+Part 3: Commands
+
+Capability Commands
+
+32.1
+
+Introduction
+
+The TPM has numerous values that indicate the state, capabilities, and properties of the TPM. These
+values are needed for proper management of the TPM. The TPM2_GetCapability() command is used to
+access these values.
+TPM2_GetCapability() allows reporting of multiple values in a single call. The values are grouped
+according to type.
+NOTE
+
+32.2
+
+TPM2_TestParms()is used to determine if a TPM supports a particular combination of algorithm
+parameters
+
+TPM2_GetCapability
+
+32.2.1 General Description
+This command returns various information regarding the TPM and its current state.
+The capability parameter determines the category of data returned. The property parameter selects the
+first value of the selected category to be returned. If there is no property that corresponds to the value of
+property, the next higher value is returned, if it exists.
+EXAMPLE 1
+
+The list of handles of transient objects currently loaded in the TPM may be read one at a time. On
+the first read, set the property to TRANSIENT_FIRST and propertyCount to one. If a transient object
+is present, the lowest numbered handle is returned and moreData will be YES if transient objects
+with higher handles are loaded. On the subsequent call, use returned handle value plus 1 in order to
+access the next higher handle.
+
+The propertyCount parameter indicates the number of capabilities in the indicated group that are
+requested. The TPM will return the number of requested values (propertyCount) or until the last property
+of the requested type has been returned.
+NOTE 1
+
+The type of the capability is determined by a combination of capability and property.
+
+When all of the properties of the requested type have been returned, the moreData parameter in the
+response will be set to NO. Otherwise, it will be set to YES.
+NOTE 2
+
+The moreData parameter will be YES if there are more properties e ven if the requested number of
+capabilities has been returned.
+
+The TPM is not required to return more than one value at a time. It is not required to provide the same
+number of values in response to subsequent requests.
+EXAMPLE 2
+
+A TPM may return 4 properties in response to a TPM2_GetCapability(capability =
+TPM_CAP_TPM_PROPERTY, property = TPM_PT_MANUFACTURER, propertyCount = 8 ) and for a
+latter request with the same parameters, the TPM may return as few as one and as many as 8
+values.
+
+When the TPM is in Failure mode, a TPM is required to allow use of this command for access of the
+following capabilities:
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 381
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+
+
+TPM_PT_MANUFACTURER
+
+
+
+TPM_PT_VENDOR_STRING_1
+
+
+
+TPM_PT_VENDOR_STRING_2
+
+(3)
+
+
+
+TPM_PT_VENDOR_STRING_3
+
+(3)
+
+
+
+TPM_PT_VENDOR_STRING_4
+
+(3)
+
+
+
+TPM_PT_VENDOR_TPM_TYPE
+
+
+
+TPM_PT_FIRMWARE_VERSION_1
+
+
+
+TPM_PT_FIRMWARE_VERSION_2
+
+NOTE 3
+
+If the vendor string does not require one of these values, the property type does not need to exist.
+
+A vendor may optionally allow the TPM to return other values.
+If in Failure mode and a capability is requested that is not available in Failure mode, the TPM shall return
+no value.
+EXAMPLE 3
+
+Assume the TPM is in Failure mode and the TPM only supports reporting of the minimum required
+set of properties (the limited set to TPML_TAGGED_PCR_PROPERTY values). If a
+TPM2_GetCapability is received requesting a capability that has a property type value greater than
+TPM_PT_FIRMWARE_VERSION_2, the TPM will return a zero length list with the moreData
+parameter set to NO. If the property type is less than TPM_PT_M ANUFACTURER, the TPM will
+return TPM_PT_MANUFACTURER.
+
+In Failure mode, tag is required to be TPM_ST_NO_SESSIONS or the TPM shall return
+TPM_RC_FAILURE.
+The capability categories and the types of the return values are:
+capability
+
+Return Type
+
+property
+(1)
+
+TPM_CAP_ALGS
+
+TPM_ALG_ID
+
+TPML_ALG_PROPERTY
+
+TPM_CAP_HANDLES
+
+TPM_HANDLE
+
+TPML_HANDLE
+
+TPM_CAP_COMMANDS
+
+TPM_CC
+
+TPML_CCA
+
+TPM_CAP_PP_COMMANDS
+
+TPM_CC
+
+TPML_CC
+
+TPM_CAP_AUDIT_COMMANDS
+
+TPM_CC
+
+TPML_CC
+
+TPM_CAP_PCRS
+
+Reserved
+
+TPML_PCR_SELECTION
+
+TPM_CAP_TPM_PROPERTIES
+
+TPM_PT
+
+TPML_TAGGED_TPM_PROPERTY
+
+TPM_CAP_PCR_PROPERTIES
+
+TPM_PT_PCR
+
+TPML_TAGGED_PCR_PROPERTY
+(1)
+
+TPM_CAP_ECC_CURVE
+
+TPM_ECC_CURVE
+
+TPM_CAP_VENDOR_PROPERTY
+
+manufacturer specific
+
+TPML_ECC_CURVE
+manufacturer-specific values
+
+NOTES:
+(1) The TPM_ALG_ID or TPM_ECC_CURVE is cast to a UINT32
+
+Page 382
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+
+
+TPM_CAP_ALGS – Returns a list of TPMS_ALG_PROPERTIES. Each entry is an algorithm ID and a
+set of properties of the algorithm.
+
+
+
+TPM_CAP_HANDLES – Returns a list of all of the handles within the handle range of the property
+parameter. The range of the returned handles is determined by the handle type (the most-significant
+octet (MSO) of the property). Any of the defined handle types is allowed
+EXAMPLE 4
+
+EXAMPLE 5
+
+
+
+If the MSO of property is TPM_HT_NV_INDEX, then the TPM will return a list of NV Index
+values.
+If the MSO of property is TPM_HT_PCR, then the TPM will return a list of PCR.
+
+For this capability, use of TPM_HT_LOADED_SESSION and TPM_HT_SAVED_SESSION is
+allowed. Requesting handles with a handle type of TPM_HT_LOADED_SESSION will return handles
+for loaded sessions. The returned handle values will have a handle type of either
+TPM_HT_HMAC_SESSION or TPM_HT_POLICY_SESSION. If saved sessions are requested, all
+returned values will have the TPM_HT_HMAC_SESSION handle type because the TPM does not
+track the session type of saved sessions.
+NOTE 2
+
+
+
+TPM_HT_LOADED_SESSION and TPM_HT_HMAC_SESSION have the same value, as do
+TPM_HT_SAVED_SESSION and TPM_HT_POLICY_SESSION. It is not possible to request that
+the TPM return a list of loaded HMAC sessions without including the policy sessions.
+
+TPM_CAP_COMMANDS – Returns a list of the command attributes for all of the commands
+implemented in the TPM, starting with the TPM_CC indicated by the property parameter. If vendor
+specific commands are implemented, the vendor-specific command attribute with the lowest
+commandIndex, is returned after the non-vendor-specific (base) command.
+NOTE 4
+
+The type of the property parameter is a TPM_CC while the type of the returned list is
+TPML_CCA.
+
+
+
+TPM_CAP_PP_COMMANDS – Returns a list of all of the commands currently requiring Physical
+Presence for confirmation of platform authorization. The list will start with the TPM_CC indicated by
+property.
+
+
+
+TPM_CAP_AUDIT_COMMANDS – Returns a list of all of the commands currently set for command
+audit.
+
+
+
+TPM_CAP_PCRS – Returns the current allocation of PCR in a TPML_PCR_SELECTION. The
+property parameter shall be zero. The TPM will always respond to this command with the full PCR
+allocation and moreData will be NO.
+
+
+
+TPM_CAP_TPM_PROPERTIES – Returns a list of tagged properties. The tag is a TPM_PT and the
+property is a 32-bit value. The properties are returned in groups. Each property group is on a 256value boundary (that is, the boundary occurs when the TPM_PT is evenly divisible by 256). The TPM
+will only return values in the same group as the property parameter in the command.
+
+
+
+TPM_CAP_PCR_PROPERTIES – Returns a list of tagged PCR properties. The tag is a
+TPM_PT_PCR and the property is a TPMS_PCR_SELECT.
+
+The input command property is a TPM_PT_PCR (see Part 2 for PCR properties to be requested) that
+specifies the first property to be returned. If propertyCount is greater than 1, the list of properties begins
+with that property and proceeds in TPM_PT_PCR sequence.
+NOTE 5
+
+If the propertyCount selects an unimplemented property, the next higher implemented property
+is returned.
+
+Each item in the list is a TPMS_PCR_SELECT structure that contains a bitmap of all PCR.
+NOTE 6
+
+A PCR index in all banks (all hash algorithms) has the same properties, so the hash algorithm is
+not specified here.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 383
+October 31, 2013
+
+ Part 3: Commands
+
+
+Trusted Platform Module Library
+
+TPM_CAP_TPM_ECC_CURVES – Returns a list of ECC curve identifiers currently available for use
+in the TPM.
+
+The moreData parameter will have a value of YES if there are more values of the requested type that
+were not returned.
+If no next capability exists, the TPM will return a zero-length list and moreData will have a value of NO.
+
+Page 384
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+32.2.2 Command and Response
+Table 193 — TPM2_GetCapability Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetCapability
+
+TPM_CAP
+
+capability
+
+group selection; determines the format of the response
+
+UINT32
+
+property
+
+further definition of information
+
+UINT32
+
+propertyCount
+
+number of properties of the indicated type to return
+
+Table 194 — TPM2_GetCapability Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_YES_NO
+
+moreData
+
+flag to indicate if there are more values of this type
+
+TPMS_CAPABILITY_DATA
+
+capabilityData
+
+the capability data
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 385
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+32.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "GetCapability_fp.h"
+Error Returns
+TPM_RC_HANDLE
+
+value of property is in an unsupported handle range for the
+TPM_CAP_HANDLES capability value
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+invalid capability; or property is not 0 for the TPM_CAP_PCRS
+capability value
+
+TPM_RC
+TPM2_GetCapability(
+GetCapability_In
+GetCapability_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Set output capability type the same as input type
+out->capabilityData.capability = in->capability;
+switch(in->capability)
+{
+case TPM_CAP_ALGS:
+out->moreData = AlgorithmCapGetImplemented((TPM_ALG_ID) in->property,
+in->propertyCount, &out->capabilityData.data.algorithms);
+break;
+case TPM_CAP_HANDLES:
+switch(HandleGetType((TPM_HANDLE) in->property))
+{
+case TPM_HT_TRANSIENT:
+// Get list of handles of loaded transient objects
+out->moreData = ObjectCapGetLoaded((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_PERSISTENT:
+// Get list of handles of persistent objects
+out->moreData = NvCapGetPersistent((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_NV_INDEX:
+// Get list of defined NV index
+out->moreData = NvCapGetIndex((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_LOADED_SESSION:
+// Get list of handles of loaded sessions
+out->moreData = SessionCapGetLoaded((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_ACTIVE_SESSION:
+// Get list of handles of
+out->moreData = SessionCapGetSaved((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+
+Page 386
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+
+Part 3: Commands
+
+break;
+case TPM_HT_PCR:
+// Get list of handles of PCR
+out->moreData = PCRCapGetHandles((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_PERMANENT:
+// Get list of permanent handles
+out->moreData = PermanentCapGetHandles(
+(TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+default:
+// Unsupported input handle type
+return TPM_RC_HANDLE + RC_GetCapability_property;
+break;
+}
+break;
+case TPM_CAP_COMMANDS:
+out->moreData = CommandCapGetCCList((TPM_CC) in->property,
+in->propertyCount,
+&out->capabilityData.data.command);
+break;
+case TPM_CAP_PP_COMMANDS:
+out->moreData = PhysicalPresenceCapGetCCList((TPM_CC) in->property,
+in->propertyCount, &out->capabilityData.data.ppCommands);
+break;
+case TPM_CAP_AUDIT_COMMANDS:
+out->moreData = CommandAuditCapGetCCList((TPM_CC) in->property,
+in->propertyCount,
+&out->capabilityData.data.auditCommands);
+break;
+case TPM_CAP_PCRS:
+// Input property must be 0
+if(in->property != 0)
+return TPM_RC_VALUE + RC_GetCapability_property;
+out->moreData = PCRCapGetAllocation(in->propertyCount,
+&out->capabilityData.data.assignedPCR);
+break;
+case TPM_CAP_PCR_PROPERTIES:
+out->moreData = PCRCapGetProperties((TPM_PT_PCR) in->property,
+in->propertyCount,
+&out->capabilityData.data.pcrProperties);
+break;
+case TPM_CAP_TPM_PROPERTIES:
+out->moreData = TPMCapGetProperties((TPM_PT) in->property,
+in->propertyCount,
+&out->capabilityData.data.tpmProperties);
+break;
+#ifdef TPM_ALG_ECC
+case TPM_CAP_ECC_CURVES:
+out->moreData = CryptCapGetECCCurve((TPM_ECC_CURVE
+) in->property,
+in->propertyCount,
+&out->capabilityData.data.eccCurves);
+break;
+#endif // TPM_ALG_ECC
+case TPM_CAP_VENDOR_PROPERTY:
+// vendor property is not implemented
+default:
+// Unexpected TPM_CAP value
+return TPM_RC_VALUE;
+break;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 387
+October 31, 2013
+
+ Part 3: Commands
+116
+117
+118
+119
+
+Trusted Platform Module Library
+
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 388
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+32.3
+
+Part 3: Commands
+
+TPM2_TestParms
+
+32.3.1 General Description
+This command is used to check to see if specific combinations of algorithm parameters are supported.
+The TPM will unmarshal the provided TPMT_PUBLIC_PARMS. If the parameters unmarshal correctly,
+then the TPM will return TPM_RC_SUCCESS, indicating that the parameters are valid for the TPM. The
+TPM will return the appropriate unmarshaling error if a parameter is not valid.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 389
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+32.3.2 Command and Response
+Table 195 — TPM2_TestParms Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_TestParms
+
+TPMT_PUBLIC_PARMS
+
+parameters
+
+algorithm parameters to be validated
+
+Table 196 — TPM2_TestParms Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 390
+October 31, 2013
+
+TPM_RC
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+32.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+#include "InternalRoutines.h"
+#include "TestParms_fp.h"
+
+TPM_RC
+TPM2_TestParms(
+TestParms_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+// Input parameter is not reference in command action
+in = NULL;
+// The parameters are tested at unmarshal process.
+// action
+return TPM_RC_SUCCESS;
+
+We do nothing in command
+
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 391
+October 31, 2013
+
+ Part 3: Commands
+
+33
+
+Trusted Platform Module Library
+
+Non-volatile Storage
+
+33.1
+
+Introduction
+
+The NV commands are used to create, update, read, and delete allocations of space in NV memory.
+Before an Index may be used, it must be defined (TPM2_NV_DefineSpace()).
+An Index may be modified if the proper write authorization is provided or read if the proper read
+authorization is provided. Different controls are available for reading and writing.
+An Index may have an Index-specific authValue and authPolicy. The authValue may be used to authorize
+reading if TPMA_NV_AUTHREAD is SET and writing if TPMA_NV_AUTHREAD is SET. The authPolicy
+may be used to authorize reading if TPMA_NV_POLICYREAD is SET and writing if
+TPMA_NV_POLICYWRITE is SET.
+TPMA_NV_PPREAD and TPMA_NV_PPWRITE indicate if reading or writing of the NV Index may be
+authorized by platformAuth or platformPolicy.
+TPMA_NV_OWNERREAD and TPMA_NV_OWNERWRITE indicate if reading or writing of the NV Index
+may be authorized by ownerAuth or ownerPolicy.
+If an operation on an NV index requires authorization, and the authHandle parameter is the handle of an
+NV Index, then the nvIndex parameter must have the same value or the TPM will return
+TPM_RC_NV_AUTHORIZATION.
+NOTE 1
+
+This check ensures that the authorization that was provided is associated with the NV Index being
+authorized.
+
+For creating an Index, ownerAuth may not be used if shEnable is CLEAR and platformAuth may not be
+used if phEnableNV is CLEAR.
+If an Index was defined using platformAuth, then that Index is not accessible when phEnableNV is
+CLEAR. If an Index was defined using ownerAuth, then that Index is not accessible when shEnable is
+CLEAR.
+For read access control, any combination of TPMA_NV_PPREAD, TPMA_NV_OWNERREAD,
+TPMA_NV_AUTHREAD, or TPMA_NV_POLICYREAD is allowed as long as at least one is SET.
+For write access control, any combination of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE,
+TPMA_NV_AUTHWRITE, or TPMA_NV_POLICYWRITE is allowed as long as at least one is SET.
+If an Index has been defined and not written, then any operation on the NV Index that requires read
+authorization will fail (TPM_RC_NV_INITIALIZED). This check may be made before or after other
+authorization checks but shall be performed before checking the NV Index authValue. An authorization
+failure due to the NV Index not having been written shall not be logged by the dictionary attack logic.
+If TPMA_NV_CLEAR_STCLEAR is SET, then the TPMA_NV_WRITTEN will be CLEAR on each
+TPM2_Startup(TPM_SU_CLEAR).
+TPMA_NV_CLEAR_STCLEAR
+shall
+not
+be
+SET
+if
+TPMA_NV_COUNTER is SET.
+The code in the “Detailed Actions” clause of each command is written to interface with an implementationdependent library that allows access to NV memory. The actions assume no specific layout of the
+structure of the NV data.
+Only one NV Index may be directly referenced in a command.
+NOTE 2
+
+This means that, if authHandle references an NV Index, then nvIndex will have the same value.
+However, this does not limit the number of changes that may occur as side effects. For example, any
+number of NV Indexes might be relocated as a result of deleting or adding a NV Ind ex.
+
+Page 392
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.2
+
+Part 3: Commands
+
+NV Counters
+
+When an Index has the TPMA_NV_COUNTER attribute set, it behaves as a monotonic counter and may
+only be updated using TPM2_NV_Increment().
+When an NV counter is created, the TPM shall initialize the 8-octet counter value with a number that is
+greater than any count value for any NV counter on the TPM since the time of TPM manufacture.
+An NV counter may be defined with the TPMA_NV_ORDERLY attribute to indicate that the NV Index is
+expected to be modified at a high frequency and that the data is only required to persist when the TPM
+goes through an orderly shutdown process. The TPM may update the counter value in RAM and
+occasionally update the non-volatile version of the counter. An orderly shutdown is one occasion to
+update the non-volatile count. If the difference between the volatile and non-volatile version of the counter
+becomes as large as MAX_ORDERLY_COUNT, this shall be another occasion for updating the nonvolatile count.
+Before an NV counter can be used, the TPM shall validate that the count is not less than a previously
+reported value. If the TPMA_NV_ORDERLY attribute is not SET, or if the TPM experienced an orderly
+shutdown, then the count is assumed to be correct. If the TPMA_NV_ORDERLY attribute is SET, and the
+TPM shutdown was not orderly, then the TPM shall OR MAX_ORDERLY_COUNT to the contents of the
+non-volatile counter and set that as the current count.
+NOTE 1
+
+Because the TPM would have updated the NV Index if the difference between the count values was
+equal to MAX_ORDERLY_COUNT + 1, the highest value that could have been in the NV Index is
+MAX_ORDERLY_COUNT so it is safe to restore that value.
+
+NOTE 2
+
+The TPM may implement the RAM portion of the counter such that the effective value of the NV
+counter is the sum of both the volatile and non-volatile parts. If so, then the TPM may initialize the
+RAM version of the counter to MAX_ORDERLY_COUNT and no update of NV is necessary.
+
+NOTE 3
+
+When a new NV counter is created, the TPM may search all the counters to determine which has the
+highest value. In this search, the TPM would use the sum of the non -volatile and RAM portions of
+the counter. The RAM portion of the counter shall be properly initialized to reflect shutdown p rocess
+(orderly or not) of the TPM.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 393
+October 31, 2013
+
+ Part 3: Commands
+
+33.3
+
+Trusted Platform Module Library
+
+TPM2_NV_DefineSpace
+
+33.3.1 General Description
+This command defines the attributes of an NV Index and causes the TPM to reserve space to hold the
+data associated with the NV Index. If a definition already exists at the NV Index, the TPM will return
+TPM_RC_NV_DEFINED.
+The TPM will return TPM_RC_ATTRIBUTES if more
+TPMA_NV_BITS, or TPMA_NV_EXTEND is SET in publicInfo.
+NOTE
+
+than
+
+one
+
+of
+
+TPMA_NV_COUNTER,
+
+It is not required that any of these three attributes be set.
+
+The TPM shall return TPM_RC_ATTRIBUTES if TPMA_NV_WRITTEN, TPM_NV_READLOCKED, or
+TPMA_NV_WRITELOCKED is SET.
+If TPMA_NV_COUNTER or TPMA_NV_BITS is SET, then publicInfo→dataSize shall be set to eight (8) or
+the TPM shall return TPM_RC_SIZE.
+If TPMA_NV_EXTEND is SET, then publicInfo→dataSize shall match the digest size of the
+publicInfo.nameAlg or the TPM shall return TPM_RC_SIZE.
+If the NV Index is an ordinary Index and publicInfo→dataSize is larger than supported by the TPM
+implementation then the TPM shall return TPM_RC_SIZE.
+NOTE
+
+The limit for the data size may vary according to the type of the index. For example, if the index is
+has TPMA_NV_ORDERLY SET, then the maximum size of an ordin ary NV Index may be less than
+the size of an ordinary NV Index that has TPMA_NV_ORDERLY CLEAR.
+
+At least one of TPMA_NV_PPREAD, TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD,
+TPMA_NV_POLICYREAD shall be SET or the TPM shall return TPM_RC_ATTRIBUTES.
+
+or
+
+At least one of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, or
+TPMA_NV_POLICYWRITE shall be SET or the TPM shall return TPM_RC_ATTRIBUTES.
+If TPMA_NV_CLEAR_STCLEAR is SET, then TPMA_NV_COUNTER shall be CLEAR or the TPM shall
+return TPM_RC_ATTRIBUTES.
+If platformAuth/platformPolicy is used for authorization, then TPMA_NV_PLATFORMCREATE shall be
+SET in publicInfo. If ownerAuth/ownerPolicy is used for authorization, TPMA_NV_PLATFORMCREATE
+shall be CLEAR in publicInfo. If TPMA_NV_PLATFORMCREATE is not set correctly for the authorization,
+the TPM shall return TPM_RC_ATTRIBUTES.
+If TPMA_NV_POLICY_DELETE is SET, then the authorization shall be with platformAuth or the TPM
+shall return TPM_RC_ATTRIBUTES.
+If the implementation does not support TPM2_NV_Increment(),
+TPM_RC_ATTRIBUTES if TPMA_NV_COUNTER is SET.
+
+the
+
+TPM
+
+shall
+
+return
+
+If the implementation does not support TPM2_NV_SetBits(),
+TPM_RC_ATTRIBUTES if TPMA_NV_BITS is SET.
+
+the
+
+TPM
+
+shall
+
+return
+
+If the implementation does not support TPM2_NV_Extend(),
+TPM_RC_ATTRIBUTES if TPMA_NV_EXTEND is SET.
+
+the
+
+TPM
+
+shall
+
+return
+
+If the implementation does not support TPM2_NV_UndefineSpaceSpecial(), the TPM shall return
+TPM_RC_ATTRIBUTES if TPMA_NV_POLICY_DELETE is SET.
+After the successful completion of this command, the NV Index exists but TPMA_NV_WRITTEN will be
+CLEAR. Any access of the NV data will return TPM_RC_NV_UINITIALIZED.
+
+Page 394
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+In some implementations, an NV Index with the TPMA_NV_COUNTER attribute may require special TPM
+resources that provide higher endurance than regular NV. For those implementations, if this command
+fails because of lack of resources, the TPM will return TPM_RC_NV_SPACE.
+The value of auth is saved in the created structure. The size of auth is limited to be no larger than the size
+of the digest produced by the NV Index's nameAlg (TPM_RC_SIZE).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 395
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.3.2 Command and Response
+Table 197 — TPM2_NV_DefineSpace Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_DefineSpace {NV}
+
+TPMI_RH_PROVISION
+
+@authHandle
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_AUTH
+
+auth
+
+the authorization value
+
+TPM2B_NV_PUBLIC
+
+publicInfo
+
+the public parameters of the NV area
+
+Table 198 — TPM2_NV_DefineSpace Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 396
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "NV_DefineSpace_fp.h"
+Error Returns
+TPM_RC_NV_ATTRIBUTES
+
+attributes of the index are not consistent
+
+TPM_RC_NV_DEFINED
+
+index already exists
+
+TPM_RC_HIERARCHY
+
+for authorizations using TPM_RH_PLATFORM phEnable_NV is
+clear.
+
+TPM_RC_NV_SPACE
+
+Insufficient space for the index
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+'auth->size' or 'publicInfo->authPolicy. size' is larger than the digest
+size of 'publicInfo->nameAlg', or 'publicInfo->dataSize' is not
+consistent with 'publicInfo->attributes'.
+
+TPM_RC
+TPM2_NV_DefineSpace(
+NV_DefineSpace_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+TPMA_NV
+UINT16
+
+result;
+attributes;
+nameSize;
+
+nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg);
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation
+// If an index is being created by the owner and shEnable is
+// clear, then we would not reach this point because ownerAuth
+// can't be given when shEnable is CLEAR. However, if phEnable
+// is SET but phEnableNV is CLEAR, we have to check here
+if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
+return TPM_RC_HIERARCHY + RC_NV_DefineSpace_authHandle;
+attributes = in->publicInfo.t.nvPublic.attributes;
+//TPMS_NV_PUBLIC validation.
+// Counters and bit fields must have a size of 8
+if (
+(attributes.TPMA_NV_COUNTER == SET || attributes.TPMA_NV_BITS == SET)
+&& (in->publicInfo.t.nvPublic.dataSize != 8))
+return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
+// check that the authPolicy consistent with hash algorithm
+if(
+in->publicInfo.t.nvPublic.authPolicy.t.size != 0
+&& in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize)
+return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
+// make sure that the authValue is not too large
+MemoryRemoveTrailingZeros(&in->auth);
+if(in->auth.t.size > nameSize)
+return TPM_RC_SIZE + RC_NV_DefineSpace_auth;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 397
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+
+Trusted Platform Module Library
+
+//TPMA_NV validation.
+// Locks may not be SET and written cannot be SET
+if(
+attributes.TPMA_NV_WRITTEN == SET
+|| attributes.TPMA_NV_WRITELOCKED == SET
+|| attributes.TPMA_NV_READLOCKED == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// There must be a way to read the index
+if(
+attributes.TPMA_NV_OWNERREAD == CLEAR
+&& attributes.TPMA_NV_PPREAD == CLEAR
+&& attributes.TPMA_NV_AUTHREAD == CLEAR
+&& attributes.TPMA_NV_POLICYREAD == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// There must be a way to write the index
+if(
+attributes.TPMA_NV_OWNERWRITE == CLEAR
+&& attributes.TPMA_NV_PPWRITE == CLEAR
+&& attributes.TPMA_NV_AUTHWRITE == CLEAR
+&& attributes.TPMA_NV_POLICYWRITE == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// Make sure that no attribute is used that is not supported by the proper
+// command
+#if CC_NV_Increment == NO
+if( attributes.TPMA_NV_COUNTER == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+#if CC_NV_SetBits == NO
+if( attributes.TPMA_NV_BITS == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+#if CC_NV_Extend == NO
+if( attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+#if CC_NV_UndefineSpaceSpecial == NO
+if( attributes.TPMA_NV_POLICY_DELETE == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+// Can be COUNTER or BITS or EXTEND but not more than one
+if( attributes.TPMA_NV_COUNTER == SET
+&& attributes.TPMA_NV_BITS == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+if(
+attributes.TPMA_NV_COUNTER == SET
+&& attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+if(
+attributes.TPMA_NV_BITS == SET
+&& attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// An index with TPMA_NV_CLEAR_STCLEAR can't be a counter
+if(
+attributes.TPMA_NV_CLEAR_STCLEAR == SET
+&& attributes.TPMA_NV_COUNTER == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// The index is allowed to have one of GLOBALLOCK or WRITEDEFINE SET
+if(
+attributes.TPMA_NV_GLOBALLOCK == SET
+&& attributes.TPMA_NV_WRITEDEFINE == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// Make sure that the creator of the index can delete the index
+
+Page 398
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+
+if(
+
+Part 3: Commands
+
+(
+
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET
+&& in->authHandle == TPM_RH_OWNER
+)
+|| (
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR
+&& in->authHandle == TPM_RH_PLATFORM
+)
+)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
+
+// If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
+// the platform
+if(
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET
+&& TPM_RH_PLATFORM != in->authHandle
+)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// If the NV index is used as a PCR, the data size must match the digest
+// size
+if(
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET
+&& in->publicInfo.t.nvPublic.dataSize != nameSize
+)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// See if the index is already defined.
+if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex))
+return TPM_RC_NV_DEFINED;
+// Internal Data Update
+// define the space. A TPM_RC_NV_SPACE error may be returned at this point
+result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth);
+if(result != TPM_RC_SUCCESS)
+return result;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 399
+October 31, 2013
+
+ Part 3: Commands
+
+33.4
+
+Trusted Platform Module Library
+
+TPM2_NV_UndefineSpace
+
+33.4.1 General Description
+This command removes an Index from the TPM.
+If nvIndex is not defined, the TPM shall return TPM_RC_HANDLE.
+If nvIndex references an Index that has its TPMA_NV_PLATFORMCREATE attribute SET, the TPM shall
+return TPM_RC_NV_AUTHORITY unless platformAuth is provided.
+NOTE
+
+An Index with TPMA_NV_PLATFORMCREATE CLEAR may be deleted with platformAuth as long as
+shEnable is SET. If shEnable is CLEAR, indexes created using ownerAuth are not accessible even
+for deletion by the platform.
+
+Page 400
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.4.2 Command and Response
+Table 199 — TPM2_NV_UndefineSpace Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_UndefineSpace {NV}
+
+TPMI_RH_PROVISION
+
+@authHandle
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to remove from NV space
+Auth Index: None
+
+Table 200 — TPM2_NV_UndefineSpace Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 401
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "NV_UndefineSpace_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+TPMA_NV_POLICY_DELETE is SET in the Index referenced by
+nvIndex so this command may not be used to delete this Index (see
+TPM2_NV_UndefineSpaceSpecial())
+
+TPM_RC_NV_AUTHORIZATION
+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
+33
+34
+35
+36
+37
+38
+
+Meaning
+
+attempt to use ownerAuth to delete an index created by the platform
+
+TPM_RC
+TPM2_NV_UndefineSpace(
+NV_UndefineSpace_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET
+if(SET == nvIndex.publicArea.attributes.TPMA_NV_POLICY_DELETE)
+return TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex;
+// The owner may only delete an index that was defined with ownerAuth. The
+// platform may delete an index that was created with either auth.
+if(
+in->authHandle == TPM_RH_OWNER
+&& nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET)
+return TPM_RC_NV_AUTHORIZATION;
+// Internal Data Update
+// Call implementation dependent internal routine to delete NV index
+NvDeleteEntity(in->nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Page 402
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.5
+
+Part 3: Commands
+
+TPM2_NV_UndefineSpaceSpecial
+
+33.5.1 General Description
+This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE
+SET.
+This command requires that the policy of the NV Index be satisfied before the NV Index may be deleted.
+Because administrative role is required, the policy must contain a command that sets the policy command
+code to TPM_CC_NV_UndefineSpaceSpecial. This indicates that the policy that is being used is a policy
+that is for this command, and not a policy that would approve another use. That is, authority to use an
+object does not grant authority to undefined the object.
+If nvIndex is not defined, the TPM shall return TPM_RC_HANDLE.
+If
+nvIndex
+references
+an
+Index
+that
+has
+its
+TPMA_NV_PLATFORMCREATE
+TPMA_NV_POLICY_DELETE attribute CLEAR, the TPM shall return TPM_RC_NV_ATTRIBUTES.
+NOTE
+
+or
+
+An
+Index
+with
+TPMA_NV_PLATFORMCREATE
+CLEAR
+may
+be
+deleted
+with
+TPM2_UndefineSpace()as long as shEnable is SET. If shEnable is CLEAR, indexes created using
+ownerAuth are not accessible even for deletion by the platform .
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 403
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.5.2 Command and Response
+Table 201 — TPM2_NV_UndefineSpaceSpecial Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_UndefineSpaceSpecial {NV}
+
+TPMI_RH_NV_INDEX
+
+@nvIndex
+
+Index to be deleted
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_RH_PLATFORM
+
+@platform
+
+TPM_RH_PLATFORM + {PP}
+Auth Index: 2
+Auth Role: USER
+
+Table 202 — TPM2_NV_UndefineSpaceSpecial Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 404
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.5.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "NV_UndefineSpaceSpecial_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+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
+33
+
+Meaning
+TPMA_NV_POLICY_DELETE is not SET in the Index referenced by
+nvIndex
+
+TPM_RC
+TPM2_NV_UndefineSpaceSpecial(
+NV_UndefineSpaceSpecial_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET
+if(CLEAR == nvIndex.publicArea.attributes.TPMA_NV_POLICY_DELETE)
+return TPM_RC_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex;
+// Internal Data Update
+// Call implementation dependent internal routine to delete NV index
+NvDeleteEntity(in->nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 405
+October 31, 2013
+
+ Part 3: Commands
+
+33.6
+
+Trusted Platform Module Library
+
+TPM2_NV_ReadPublic
+
+33.6.1 General Description
+This command is used to read the public area and Name of an NV Index. The public area of an Index is
+not privacy-sensitive and no authorization is required to read this data.
+
+Page 406
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.6.2 Command and Response
+Table 203 — TPM2_NV_ReadPublic Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_ReadPublic
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index
+Auth Index: None
+
+Table 204 — TPM2_NV_ReadPublic Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_NV_PUBLIC
+
+nvPublic
+
+the public area of the NV Index
+
+TPM2B_NAME
+
+nvName
+
+the Name of the nvIndex
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 407
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.6.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
+#include "InternalRoutines.h"
+#include "NV_ReadPublic_fp.h"
+
+TPM_RC
+TPM2_NV_ReadPublic(
+NV_ReadPublic_In
+NV_ReadPublic_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+NV_INDEX
+
+nvIndex;
+
+// Command Output
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Copy data to output
+out->nvPublic.t.nvPublic = nvIndex.publicArea;
+// Compute NV name
+out->nvName.t.size = NvGetName(in->nvIndex, &out->nvName.t.name);
+return TPM_RC_SUCCESS;
+}
+
+Page 408
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.7
+
+Part 3: Commands
+
+TPM2_NV_Write
+
+33.7.1 General Description
+This command writes a value to an area in NV memory that was previously defined by
+TPM2_NV_DefineSpace().
+Proper authorizations are required for this command as determined by TPMA_NV_PPWRITE;
+TPMA_NV_OWNERWRITE; TPMA_NV_AUTHWRITE; and, if TPMA_NV_POLICY_WRITE is SET, the
+authPolicy of the NV Index.
+If the TPMA_NV_WRITELOCKED attribute of the NV Index is SET, then the TPM shall return
+TPM_RC_NV_LOCKED.
+NOTE 1
+
+If authorization sessions are present, they are checked before checks to see if writes to the NV
+Index are locked.
+
+If TPMA_NV_COUNTER, TPMA_NV_BITS or TPMA_NV_EXTEND of the NV Index is SET, then the
+TPM shall return TPM_RC_NV_ATTRIBUTE.
+If the size of the data parameter plus the offset parameter adds to a value that is greater than the size of
+the NV Index data, the TPM shall return TPM_RC_NV_RANGE and not write any data to the NV Index.
+If the TPMA_NV_WRITEALL attribute of the NV Index is SET, then the TPM shall return
+TPM_RC_NV_RANGE if the size of the data parameter of the command is not the same as the data field
+of the NV Index.
+If all checks succeed, the TPM will merge the data.size octets of data.buffer value into the nvIndex→data
+starting at nvIndex→data[offset]. If the NV memory is implemented with a technology that has endurance
+limitations, the TPM shall check that the merged data is different from the current contents of the NV
+Index and only perform a write to NV memory if they differ.
+After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
+NOTE 2
+
+Once SET, TPMA_NV_WRITTEN remains SET until the NV Index is undefined or the NV Index is
+cleared.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 409
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.7.2 Command and Response
+Table 205 — TPM2_NV_Write Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Write {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index of the area to write
+Auth Index: None
+
+TPM2B_MAX_NV_BUFFER
+
+data
+
+the data to write
+
+UINT16
+
+offset
+
+the offset into the NV Area
+
+Table 206 — TPM2_NV_Write Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 410
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.7.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "NV_Write_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+Index referenced by nvIndex has either TPMA_NV_BITS,
+TPMA_NV_COUNTER, or TPMA_NV_EVENT attribute SET
+
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+
+Index referenced by nvIndex is write locked
+
+TPM_RC_NV_RANGE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+
+Meaning
+
+if TPMA_NV_WRITEALL is SET then the write is not the size of the
+Index referenced by nvIndex; otherwise, the write extends beyond the
+limits of the Index
+
+TPM_RC
+TPM2_NV_Write(
+NV_Write_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+NV_INDEX
+TPM_RC
+
+nvIndex;
+result;
+
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// common access checks. NvWrtieAccessChecks() may return
+// TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Bits index, extend index or counter index may not be updated by
+// TPM2_NV_Write
+if(
+nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
+|| nvIndex.publicArea.attributes.TPMA_NV_BITS == SET
+|| nvIndex.publicArea.attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES;
+// Too much data
+if((in->data.t.size + in->offset) > nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// If this index requires a full sized write, make sure that input range is
+// full sized
+if(
+nvIndex.publicArea.attributes.TPMA_NV_WRITEALL == SET
+&& in->data.t.size < nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// Internal Data Update
+// Perform the write. This called routine will SET the TPMA_NV_WRITTEN
+// attribute if it has not already been SET. If NV isn't available, an error
+// will be returned.
+return NvWriteIndexData(in->nvIndex, &nvIndex, in->offset,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 411
+October 31, 2013
+
+ Part 3: Commands
+46
+47
+48
+
+Trusted Platform Module Library
+in->data.t.size, in->data.t.buffer);
+
+}
+
+Page 412
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.8
+
+Part 3: Commands
+
+TPM2_NV_Increment
+
+33.8.1 General Description
+This command is used to increment the value in an NV Index that has TPMA_NV_COUNTER SET. The
+data value of the NV Index is incremented by one.
+NOTE 1
+
+The NV Index counter is an unsigned value.
+
+If TPMA_NV_COUNTER
+TPM_RC_ATTRIBUTES.
+
+is
+
+not
+
+SET
+
+in
+
+the
+
+indicated
+
+NV
+
+Index,
+
+the
+
+TPM
+
+shall
+
+return
+
+If TPMA_NV_WRITELOCKED is SET, the TPM shall return TPM_RC_NV_LOCKED.
+If TPMA_NV_WRITTEN is CLEAR, it will be SET.
+If TPMA_NV_ORDERLY is SET, and the difference between the volatile and non-volatile versions of this
+field is greater than MAX_ORDERLY_COUNT, then the non-volatile version of the counter is updated.
+NOTE 2
+
+If a TPM implements TPMA_NV_ORDERLY and an Index is defined with TPMA_NV_ORDERLY and
+TPM_NV_COUNTER both SET, then in the Event of a non-orderly shutdown, the non-volatile value
+for the counter Index will be advanced by MAX_ORDERLY_COUNT at the next TPM2_Startup().
+
+NOTE 3
+
+An allowed implementation would keep a counter value in NV and a resettable counter in RAM. The
+reported value of the NV Index would be the sum of the two values. When the RAM count increments
+past the maximum allowed value (MAX_ORDERLY_COUNT), the non-volatile version of the count is
+updated with the sum of the values and the RAM count is reset to zero.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 413
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.8.2 Command and Response
+Table 207 — TPM2_NV_Increment Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Increment {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to increment
+Auth Index: None
+
+Table 208 — TPM2_NV_Increment Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 414
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.8.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "NV_Increment_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+NV index is not a counter
+
+TPM_RC_NV_AUTHORIZATION
+
+authorization failure
+
+TPM_RC_NV_LOCKED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+Index is write locked
+
+TPM_RC
+TPM2_NV_Increment(
+NV_Increment_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+UINT64
+
+result;
+nvIndex;
+countValue;
+
+// Input Validation
+// Common access checks, a TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Make sure that this is a counter
+if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER != SET)
+return TPM_RC_ATTRIBUTES + RC_NV_Increment_nvIndex;
+// Internal Data Update
+// If counter index is not been written, initialize it
+if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+countValue = NvInitialCounter();
+else
+// Read NV data in native format for TPM CPU.
+NvGetIntIndexData(in->nvIndex, &nvIndex, &countValue);
+// Do the increment
+countValue++;
+// If this is an orderly counter that just rolled over, need to be able to
+// write to NV to proceed. This check is done here, because NvWriteIndexData()
+// does not see if the update is for counter rollover.
+if(
+nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET
+&& (countValue & MAX_ORDERLY_COUNT) == 0)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Need to force an NV update
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 415
+October 31, 2013
+
+ Part 3: Commands
+52
+53
+54
+55
+56
+57
+58
+59
+60
+
+Trusted Platform Module Library
+
+g_updateNV = TRUE;
+}
+// Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may
+// be returned at this point. If necessary, this function will set the
+// TPMA_NV_WRITTEN attribute
+return NvWriteIndexData(in->nvIndex, &nvIndex, 0, 8, &countValue);
+}
+
+Page 416
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.9
+
+Part 3: Commands
+
+TPM2_NV_Extend
+
+33.9.1 General Description
+This command extends a value to an area in NV memory that was previously defined by
+TPM2_NV_DefineSpace.
+If TPMA_NV_EXTEND is not SET, then the TPM shall return TPM_RC_ATTRIBUTES.
+Proper write authorizations are required for this command as determined by TPMA_NV_PPWRITE,
+TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, and the authPolicy of the NV Index.
+After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
+NOTE 1
+
+Once SET, TPMA_NV_WRITTEN remains SET until the NV Index is undefined or the NV Index is
+cleared.
+
+If the TPMA_NV_WRITELOCKED attribute of the NV Index is SET, then the TPM shall return
+TPM_RC_NV_LOCKED.
+NOTE 2
+
+If authorization sessions are present, they are checked before checks to see if writes to the NV
+Index are locked.
+
+The data.buffer parameter may be larger than the defined size of the NV Index.
+The Index will be updated by:
+
+nvIndex→datanew ≔ HnameAkg(nvIndex→dataold || data.buffer)
+
+(39)
+
+where
+
+HnameAkg()
+
+the hash algorithm indicated in nvIndex→nameAlg
+
+nvIndex→data
+
+the value of the data field in the NV Index
+
+data.buffer
+
+the data buffer of the command parameter
+
+NOTE 3
+
+If TPMA_NV_WRITTEN is CLEAR, then nvIndex→data is a Zero Digest.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 417
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.9.2 Command and Response
+Table 209 — TPM2_NV_Extend Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Extend {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to extend
+Auth Index: None
+
+TPM2B_MAX_NV_BUFFER
+
+data
+
+the data to extend
+
+Table 210 — TPM2_NV_Extend Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 418
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.9.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "NV_Extend_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+the TPMA_NV_EXTEND attribute is not SET in the Index referenced
+by nvIndex
+
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+the Index referenced by nvIndex is locked for writing
+
+TPM_RC
+TPM2_NV_Extend(
+NV_Extend_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+TPM2B_DIGEST
+TPM2B_DIGEST
+HASH_STATE
+
+oldDigest;
+newDigest;
+hashState;
+
+// Input Validation
+// Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
+// or TPM_RC_NV_LOCKED
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Make sure that this is an extend index
+if(nvIndex.publicArea.attributes.TPMA_NV_EXTEND != SET)
+return TPM_RC_ATTRIBUTES + RC_NV_Extend_nvIndex;
+// If the Index is not-orderly, or if this is the first write, NV will
+// need to be updated.
+if(
+nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == CLEAR
+|| nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+{
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Internal Data Update
+// Perform the write.
+oldDigest.t.size = CryptGetHashDigestSize(nvIndex.publicArea.nameAlg);
+if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
+{
+NvGetIndexData(in->nvIndex, &nvIndex, 0,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 419
+October 31, 2013
+
+ Part 3: Commands
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+
+Trusted Platform Module Library
+
+oldDigest.t.size, oldDigest.t.buffer);
+}
+else
+{
+MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size);
+}
+// Start hash
+newDigest.t.size = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState);
+// Adding old digest
+CryptUpdateDigest2B(&hashState, &oldDigest.b);
+// Adding new data
+CryptUpdateDigest2B(&hashState, &in->data.b);
+// Complete hash
+CryptCompleteHash2B(&hashState, &newDigest.b);
+// Write extended hash back.
+// Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary
+return NvWriteIndexData(in->nvIndex, &nvIndex, 0,
+newDigest.t.size, newDigest.t.buffer);
+}
+
+Page 420
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.10 TPM2_NV_SetBits
+33.10.1
+
+General Description
+
+This command is used to SET bits in an NV Index that was created as a bit field. Any number of bits from
+0 to 64 may be SET. The contents of data are ORed with the current contents of the NV Index starting at
+offset. The checks on data and offset are the same as for TPM2_NV_Write.
+If TPMA_NV_WRITTEN is not SET, then, for the purposes of this command, the NV Index is considered
+to contain all zero bits and data is OR with that value.
+If TPMA_NV_BITS is not SET, then the TPM shall return TPM_RC_ATTRIBUTES.
+After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
+NOTE
+
+TPMA_NV_WRITTEN will be SET even if no bits were SET.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 421
+October 31, 2013
+
+ Part 3: Commands
+
+33.10.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 211 — TPM2_NV_SetBits Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_SetBits {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+NV Index of the area in which the bit is to be set
+Auth Index: None
+
+UINT64
+
+bits
+
+the data to OR with the current contents
+
+Table 212 — TPM2_NV_SetBits Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 422
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.10.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_SetBits_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+the TPMA_NV_BITS attribute is not SET in the Index referenced by
+nvIndex
+
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+the Index referenced by nvIndex is locked for writing
+
+TPM_RC
+TPM2_NV_SetBits(
+NV_SetBits_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+UINT64
+
+result;
+nvIndex;
+bitValue;
+
+// Input Validation
+// Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
+// or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Make sure that this is a bit field
+if(nvIndex.publicArea.attributes.TPMA_NV_BITS != SET)
+return TPM_RC_ATTRIBUTES + RC_NV_SetBits_nvIndex;
+// If the Index is not-orderly, or if this is the first write, NV will
+// need to be updated.
+if(
+nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == CLEAR
+|| nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+{
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Internal Data Update
+// If index is not been written, initialize it
+if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+bitValue = 0;
+else
+// Read index data
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 423
+October 31, 2013
+
+ Part 3: Commands
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+
+Trusted Platform Module Library
+
+NvGetIntIndexData(in->nvIndex, &nvIndex, &bitValue);
+// OR in the new bit setting
+bitValue |= in->bits;
+// Write index data back. If necessary, this function will SET
+// TPMA_NV_WRITTEN.
+return NvWriteIndexData(in->nvIndex, &nvIndex, 0, 8, &bitValue);
+}
+
+Page 424
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.11 TPM2_NV_WriteLock
+33.11.1
+
+General Description
+
+If the TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR attributes of an NV location are SET,
+then this command may be used to inhibit further writes of the NV Index.
+Proper write authorization is required for this command as determined by TPMA_NV_PPWRITE,
+TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, and the authPolicy of the NV Index.
+It is not an error if TPMA_NV_WRITELOCKED for the NV Index is already SET.
+If neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR of the NV Index is SET, then the
+TPM shall return TPM_RC_ATTRIBUTES.
+If the command is properly authorized and TPMA_NV_WRITE_STCLEAR or TPMA_NV_WRITEDEFINE
+is SET, then the TPM shall SET TPMA_NV_WRITELOCKED for the NV Index.
+TPMA_NV_WRITELOCKED will be clear on the next TPM2_Startup(TPM_SU_CLEAR) unless
+TPMA_NV_WRITEDEFINE is SET.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 425
+October 31, 2013
+
+ Part 3: Commands
+
+33.11.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 213 — TPM2_NV_WriteLock Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_WriteLock {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index of the area to lock
+Auth Index: None
+
+Table 214 — TPM2_NV_WriteLock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 426
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.11.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_WriteLock_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+neither TPMA_NV_WRITEDEFINE nor
+TPMA_NV_WRITE_STCLEAR is SET in Index referenced by
+nvIndex
+
+TPM_RC_NV_AUTHORIZATION
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+Meaning
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC
+TPM2_NV_WriteLock(
+NV_WriteLock_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation:
+// Common write access checks, a TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_NV_AUTHORIZATION)
+return TPM_RC_NV_AUTHORIZATION;
+// If write access failed because the index is already locked, then it is
+// no error.
+return TPM_RC_SUCCESS;
+}
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// if non of TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR is set, the index
+// can not be write-locked
+if(
+nvIndex.publicArea.attributes.TPMA_NV_WRITEDEFINE == CLEAR
+&& nvIndex.publicArea.attributes.TPMA_NV_WRITE_STCLEAR == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_WriteLock_nvIndex;
+// Internal Data Update
+// Set the WRITELOCK attribute
+nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET;
+// Write index info back
+NvWriteIndexInfo(in->nvIndex, &nvIndex);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 427
+October 31, 2013
+
+ Part 3: Commands
+51
+52
+
+Trusted Platform Module Library
+
+return TPM_RC_SUCCESS;
+}
+
+Page 428
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.12 TPM2_NV_GlobalWriteLock
+33.12.1
+
+General Description
+
+The command will SET TPMA_NV_WRITELOCKED
+TPMA_NV_GLOBALLOCK attribute SET.
+
+for
+
+all
+
+indexes
+
+that
+
+have
+
+their
+
+If an Index has both TPMA_NV_WRITELOCKED and TPMA_NV_WRITEDEFINE SET, then this
+command will permanently lock the NV Index for writing.
+NOTE
+
+If an Index is defined with TPMA_NV_GLOBALLOCK SET, then the global lock does not apply until
+the next time this command is executed.
+
+This command requires either platformAuth/platformPolicy or ownerAuth/ownerPolicy.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 429
+October 31, 2013
+
+ Part 3: Commands
+
+33.12.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 215 — TPM2_NV_GlobalWriteLock Command
+
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_GlobalWriteLock
+
+@authHandle
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_PROVISION
+
+Description
+
+Table 216 — TPM2_NV_GlobalWriteLock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 430
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.12.3
+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
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_GlobalWriteLock_fp.h"
+
+TPM_RC
+TPM2_NV_GlobalWriteLock(
+NV_GlobalWriteLock_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input parameter is not reference in command action
+in = NULL; // to silence compiler warnings.
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+// Implementation dependent method of setting the global lock
+NvSetGlobalLock();
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 431
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.13 TPM2_NV_Read
+33.13.1
+
+General Description
+
+This command reads a
+TPM2_NV_DefineSpace().
+
+value
+
+from
+
+an
+
+area
+
+in
+
+NV
+
+memory
+
+previously
+
+defined
+
+by
+
+Proper authorizations are required for this command as determined by TPMA_NV_PPREAD,
+TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD, and the authPolicy of the NV Index.
+If TPMA_NV_READLOCKED of the NV Index is SET, then the TPM shall return TPM_RC_NV_LOCKED.
+NOTE
+
+If authorization sessions are present, they are checked before the read -lock status of the NV Index
+is checked.
+
+If the size parameter plus the offset parameter adds to a value that is greater than the size of the NV
+Index data area, the TPM shall return TPM_RC_NV_RANGE and not read any data from the NV Index.
+If the NV Index has been defined but the TPMA_NV_WRITTEN attribute is CLEAR, then this command
+shall return TPM_RC_NV_UINITIALIZED even if size is zero.
+The data parameter in the response may be encrypted using parameter encryption.
+
+Page 432
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.13.2
+
+Part 3: Commands
+
+Command and Response
+Table 217 — TPM2_NV_Read Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Read
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+the handle indicating the source of the authorization
+value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to be read
+Auth Index: None
+
+UINT16
+
+size
+
+number of octets to read
+
+UINT16
+
+offset
+
+octet offset into the area
+This value shall be less than or equal to the size of the
+nvIndex data.
+
+Table 218 — TPM2_NV_Read Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_NV_BUFFER
+
+data
+
+Family “2.0”
+Level 00 Revision 00.99
+
+the data read
+
+Published
+Copyright © TCG 2006-2013
+
+Page 433
+October 31, 2013
+
+ Part 3: Commands
+
+33.13.3
+1
+2
+3
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_Read_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to read from the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+
+the Index referenced by nvIndex is read locked
+
+TPM_RC_NV_RANGE
+
+read range defined by size and offset is outside the range of the
+Index referenced by nvIndex
+
+TPM_RC_NV_UNINITIALIZED
+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
+33
+34
+35
+36
+37
+
+Meaning
+
+the Index referenced by nvIndex has not been initialized (written)
+
+TPM_RC
+TPM2_NV_Read(
+NV_Read_In
+NV_Read_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+NV_INDEX
+TPM_RC
+
+nvIndex;
+result;
+
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Common read access checks. NvReadAccessChecks() returns
+// TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
+// error may be returned at this point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Too much data
+if((in->size + in->offset) > nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// Command Output
+// Set the return size
+out->data.t.size = in->size;
+// Perform the read
+NvGetIndexData(in->nvIndex, &nvIndex, in->offset, in->size, out->data.t.buffer);
+return TPM_RC_SUCCESS;
+}
+
+Page 434
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.14 TPM2_NV_ReadLock
+33.14.1
+
+General Description
+
+If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent further
+reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR).
+Proper authorizations are required for this command as determined by TPMA_NV_PPREAD,
+TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD, and the authPolicy of the NV Index.
+NOTE
+
+Only an entity that may read an Index is allowed to lock the NV Index for read.
+
+If the command is properly authorized and TPMA_NV_READ_STCLEAR of the NV Index is SET, then the
+TPM shall SET TPMA_NV_READLOCKED for the NV Index. If TPMA_NV_READ_STCLEAR of the NV
+Index is CLEAR, then the TPM shall return TPM_RC_NV_ATTRIBUTE. TPMA_NV_READLOCKED will
+be CLEAR by the next TPM2_Startup(TPM_SU_CLEAR).
+It is not an error to use this command for an Index that is already locked for reading.
+An Index that had not been written may be locked for reading.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 435
+October 31, 2013
+
+ Part 3: Commands
+
+33.14.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 219 — TPM2_NV_ReadLock Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_ReadLock
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+the handle indicating the source of the authorization
+value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to be locked
+Auth Index: None
+
+Table 220 — TPM2_NV_ReadLock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 436
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.14.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_ReadLock_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+TPMA_NV_READ_STCLEAR is not SET so Index referenced by
+nvIndex may not be write locked
+
+TPM_RC_NV_AUTHORIZATION
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to read from the Index referenced by nvIndex
+
+TPM_RC
+TPM2_NV_ReadLock(
+NV_ReadLock_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// Common read access checks. NvReadAccessChecks() returns
+// TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
+// error may be returned at this point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_NV_AUTHORIZATION)
+return TPM_RC_NV_AUTHORIZATION;
+// Index is already locked for write
+else if(result == TPM_RC_NV_LOCKED)
+return TPM_RC_SUCCESS;
+// If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue.
+// It is not an error to read lock an uninitialized Index.
+}
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked
+if(nvIndex.publicArea.attributes.TPMA_NV_READ_STCLEAR == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_ReadLock_nvIndex;
+// Internal Data Update
+// Set the READLOCK attribute
+nvIndex.publicArea.attributes.TPMA_NV_READLOCKED = SET;
+// Write NV info back
+NvWriteIndexInfo(in->nvIndex, &nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 437
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.15 TPM2_NV_ChangeAuth
+33.15.1
+
+General Description
+
+This command allows the authorization secret for an NV Index to be changed.
+If successful, the authorization secret (authValue) of the NV Index associated with nvIndex is changed.
+This command requires that a policy session be used for authorization of nvIndex so that the ADMIN role
+may be asserted and that commandCode in the policy session context shall be
+TPM_CC_NV_ChangeAuth. That is, the policy must contain a specific authorization for changing the
+authorization value of the referenced object.
+NOTE
+
+The reason for this restriction is to ensure that the admin istrative actions on nvIndex require explicit
+approval while other commands may use policy that is not command -dependent.
+
+The size of the newAuth value may be no larger than the size of authorization indicated when the NV
+Index was defined.
+Since the NV Index authorization is changed before the response HMAC is calculated, the newAuth value
+is used when generating the response HMAC key if required. See Part 4 ComputeResponseHMAC().
+
+Page 438
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.15.2
+
+Part 3: Commands
+
+Command and Response
+Table 221 — TPM2_NV_ChangeAuth Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_ChangeAuth {NV}
+
+TPMI_RH_NV_INDEX
+
+@nvIndex
+
+handle of the object
+Auth Index: 1
+Auth Role: ADMIN
+
+TPM2B_AUTH
+
+newAuth
+
+new authorization value
+
+Table 222 — TPM2_NV_ChangeAuth Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 439
+October 31, 2013
+
+ Part 3: Commands
+
+33.15.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_ChangeAuth_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+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
+33
+34
+35
+
+Meaning
+newAuth size is larger than the digest size of the Name algorithm for
+the Index referenced by 'nvIndex
+
+TPM_RC
+TPM2_NV_ChangeAuth(
+NV_ChangeAuth_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// Input Validation
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Read index info from NV
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Remove any trailing zeros that might have been added by the caller
+// to obfuscate the size.
+MemoryRemoveTrailingZeros(&(in->newAuth));
+// Make sure that the authValue is no larger than the nameAlg of the Index
+if(in->newAuth.t.size > CryptGetHashDigestSize(nvIndex.publicArea.nameAlg))
+return TPM_RC_SIZE + RC_NV_ChangeAuth_newAuth;
+// Internal Data Update
+// Change auth
+nvIndex.authValue = in->newAuth;
+// Write index info back to NV
+NvWriteIndexInfo(in->nvIndex, &nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Page 440
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.16 TPM2_NV_Certify
+33.16.1
+
+General Description
+
+The purpose of this command is to certify the contents of an NV Index or portion of an NV Index.
+If proper authorization for reading the NV Index is provided, the portion of the NV Index selected by size
+and offset are included in an attestation block and signed using the key indicated by signHandle. The
+attestation also includes size and offset so that the range of the data can be determined.
+NOTE
+
+See 20.1 for description of how the signing scheme is selected.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 441
+October 31, 2013
+
+ Part 3: Commands
+
+33.16.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 223 — TPM2_NV_Certify Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Certify
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the key used to sign the attestation structure
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+for the NV Index
+Auth Index: 2
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+Index for the area to be certified
+Auth Index: None
+
+TPM2B_DATA
+
+qualifyingData
+
+user-provided qualifying data
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+UINT16
+
+size
+
+number of octets to certify
+
+UINT16
+
+offset
+
+octet offset into the area
+This value shall be less than or equal to the size of the
+nvIndex data.
+
+Table 224 — TPM2_NV_Certify Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+.
+
+TPM2B_ATTEST
+
+certifyInfo
+
+the structure that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the asymmetric signature over certifyInfo using the key
+referenced by signHandle
+
+Page 442
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.16.3
+1
+2
+3
+4
+
+Detailed Actions
+
+#include
+#include
+#include
+#include
+
+Part 3: Commands
+
+"InternalRoutines.h"
+"Attest_spt_fp.h"
+"NV_spt_fp.h"
+"NV_Certify_fp.h"
+
+Error Returns
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to read from the Index referenced by nvIndex
+
+TPM_RC_KEY
+
+signHandle does not reference a signing key
+
+TPM_RC_NV_LOCKED
+
+Index referenced by nvIndex is locked for reading
+
+TPM_RC_NV_RANGE
+
+offset plus size extends outside of the data range of the Index
+referenced by nvIndex
+
+TPM_RC_NV_UNINITIALIZED
+
+Index referenced by nvIndex has not been written
+
+TPM_RC_SCHEME
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+inScheme is not an allowed value for the key definition
+
+TPM_RC
+TPM2_NV_Certify(
+NV_Certify_In
+NV_Certify_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+TPMS_ATTEST
+
+result;
+nvIndex;
+certifyInfo;
+
+// Attestation command may cause the orderlyState to be cleared due to
+// the reporting of clock info. If this is the case, check if NV is
+// available first
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Common access checks. A TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// See if the range to be certified is out of the bounds of the defined
+// Index
+if((in->size + in->offset) > nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// Command Output
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 443
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+
+Trusted Platform Module Library
+
+// Filling in attest information
+// Common fields
+// FillInAttestInfo can return TPM_RC_SCHEME or TPM_RC_KEY
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&certifyInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_NV_Certify_signHandle;
+else
+return RcSafeAddToResult(result, RC_NV_Certify_inScheme);
+}
+// NV certify specific fields
+// Attestation type
+certifyInfo.type = TPM_ST_ATTEST_NV;
+// Get the name of the index
+certifyInfo.attested.nv.indexName.t.size =
+NvGetName(in->nvIndex, &certifyInfo.attested.nv.indexName.t.name);
+// Set the return size
+certifyInfo.attested.nv.nvContents.t.size = in->size;
+// Set the offset
+certifyInfo.attested.nv.offset = in->offset;
+// Perform the read
+NvGetIndexData(in->nvIndex, &nvIndex,
+in->offset, in->size,
+certifyInfo.attested.nv.nvContents.t.buffer);
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. SignAttestInfo() may return TPM_RC_VALUE,
+// TPM_RC_SCHEME or TPM_RC_ATTRUBUTES.
+// Note: SignAttestInfo may return TPM_RC_ATTRIBUTES if the key is not a
+// signing key but that was checked above. TPM_RC_VALUE would mean that the
+// data to sign is too large but the data to sign is a digest
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&certifyInfo,
+&in->qualifyingData,
+&out->certifyInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 444
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ \ No newline at end of file
diff --git a/trunks/generator/raw_commands_fixed.txt b/trunks/generator/raw_commands_fixed.txt
new file mode 100644
index 0000000..72e2963
--- /dev/null
+++ b/trunks/generator/raw_commands_fixed.txt
@@ -0,0 +1,35665 @@
+Trusted Platform Module Library
+Part 3: Commands
+Family “2.0”
+Level 00 Revision 00.99
+October 31, 2013
+
+Contact: admin@trustedcomputinggroup.org
+
+Published
+Copyright © TCG 2006-2013
+
+TCG
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Licenses and Notices
+1. Copyright Licenses:
+
+
+Trusted Computing Group (TCG) grants to the user of the source code in this specification (the
+“Source Code”) a worldwide, irrevocable, nonexclusive, royalty free, copyright license to
+reproduce, create derivative works, distribute, display and perform the Source Code and
+derivative works thereof, and to grant others the rights granted herein.
+
+
+
+The TCG grants to the user of the other parts of the specification (other than the Source Code)
+the rights to reproduce, distribute, display, and perform the specification solely for the purpose of
+developing products based on such documents.
+
+2. Source Code Distribution Conditions:
+
+
+Redistributions of Source Code must retain the above copyright licenses, this list of conditions
+and the following disclaimers.
+
+
+
+Redistributions in binary form must reproduce the above copyright licenses, this list of conditions
+and the following disclaimers in the documentation and/or other materials provided with the
+distribution.
+
+3. Disclaimers:
+
+
+THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF
+LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH
+RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)
+THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.
+Contact TCG Administration (admin@trustedcomputinggroup.org) for information on specification
+licensing rights available through TCG membership agreements.
+
+
+
+THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES
+WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF
+INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF
+ANY PROPOSAL, SPECIFICATION OR SAMPLE.
+
+
+
+Without limitation, TCG and its members and licensors disclaim all liability, including liability for
+infringement of any proprietary rights, relating to use of information in this specification and to the
+implementation of this specification, and TCG disclaims all liability for cost of procurement of
+substitute goods or services, lost profits, loss of use, loss of data or any incidental, consequential,
+direct, indirect, or special damages, whether under contract, tort, warranty or otherwise, arising in
+any way out of use or reliance upon this specification or any information herein.
+
+Any marks and brands contained herein are the property of their respective owner
+
+Page ii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+CONTENTS
+1
+2
+3
+4
+
+Scope .................................................................................................................................................... 1
+Terms and Definitions ........................................................................................................................... 1
+Symbols and abbreviated terms ............................................................................................................ 1
+Notation ................................................................................................................................................. 1
+4.1
+4.2
+4.3
+4.4
+
+5
+6
+7
+
+Introduction ..................................................................................................................................... 1
+Table Decorations ........................................................................................................................... 1
+Handle and Parameter Demarcation .............................................................................................. 3
+AuthorizationSize and ParameterSize ............................................................................................ 3
+
+Normative References ........................................................................................................................... 4
+Symbols and Abbreviated Terms .......................................................................................................... 4
+Command Processing ........................................................................................................................... 4
+7.1
+7.2
+7.3
+7.4
+7.5
+7.6
+7.7
+7.8
+7.9
+
+8
+
+Introduction ..................................................................................................................................... 4
+Command Header Validation .......................................................................................................... 4
+Mode Checks .................................................................................................................................. 4
+Handle Area Validation ................................................................................................................... 5
+Session Area Validation .................................................................................................................. 6
+Authorization Checks ...................................................................................................................... 7
+Parameter Decryption ..................................................................................................................... 8
+Parameter Unmarshaling ................................................................................................................ 9
+Command Post Processing .......................................................................................................... 10
+
+Response Values ................................................................................................................................ 12
+8.1
+8.2
+
+9
+10
+
+Implementation Dependent ................................................................................................................. 15
+Detailed Actions Assumptions ............................................................................................................. 16
+
+10.1
+10.2
+10.3
+11
+
+Introduction ................................................................................................................................... 28
+TPM2_SelfTest ............................................................................................................................. 29
+TPM2_IncrementalSelfTest .......................................................................................................... 32
+TPM2_GetTestResult ................................................................................................................... 35
+
+Session Commands ............................................................................................................................ 38
+
+13.1
+13.2
+14
+
+Introduction ................................................................................................................................... 17
+_TPM_Init...................................................................................................................................... 17
+TPM2_Startup ............................................................................................................................... 19
+TPM2_Shutdown .......................................................................................................................... 24
+
+Testing ................................................................................................................................................. 28
+
+12.1
+12.2
+12.3
+12.4
+13
+
+Introduction ................................................................................................................................... 16
+Pre-processing .............................................................................................................................. 16
+Post Processing ............................................................................................................................ 16
+
+Start-up ................................................................................................................................................ 17
+
+11.1
+11.2
+11.3
+11.4
+12
+
+Tag ................................................................................................................................................ 12
+Response Codes .......................................................................................................................... 12
+
+TPM2_StartAuthSession .............................................................................................................. 38
+TPM2_PolicyRestart ..................................................................................................................... 43
+
+Object Commands............................................................................................................................... 46
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page iii
+October 31, 2013
+
+ Part 3: Commands
+14.1
+14.2
+14.3
+14.4
+14.5
+14.6
+14.7
+14.8
+15
+
+Introduction ................................................................................................................................. 132
+TPM2_HMAC_Start .................................................................................................................... 132
+TPM2_HashSequenceStart ........................................................................................................ 136
+TPM2_SequenceUpdate ............................................................................................................ 139
+TPM2_SequenceComplete......................................................................................................... 143
+TPM2_EventSequenceComplete ............................................................................................... 147
+
+Attestation Commands ...................................................................................................................... 151
+
+20.1
+20.2
+20.3
+20.4
+20.5
+20.6
+20.7
+21
+
+TPM2_GetRandom ..................................................................................................................... 126
+TPM2_StirRandom ..................................................................................................................... 129
+
+Hash/HMAC/Event Sequences ......................................................................................................... 132
+
+19.1
+19.2
+19.3
+19.4
+19.5
+19.6
+20
+
+Introduction ................................................................................................................................. 113
+TPM2_EncryptDecrypt ................................................................................................................ 115
+TPM2_Hash ................................................................................................................................ 119
+TPM2_HMAC .............................................................................................................................. 122
+
+Random Number Generator .............................................................................................................. 126
+
+18.1
+18.2
+19
+
+Introduction ................................................................................................................................... 92
+TPM2_RSA_Encrypt ..................................................................................................................... 92
+TPM2_RSA_Decrypt .................................................................................................................... 97
+TPM2_ECDH_KeyGen ............................................................................................................... 101
+TPM2_ECDH_ZGen ................................................................................................................... 104
+TPM2_ECC_Parameters ............................................................................................................ 107
+TPM2_ZGen_2Phase ................................................................................................................. 108
+
+Symmetric Primitives ......................................................................................................................... 113
+
+17.1
+17.2
+17.3
+17.4
+18
+
+TPM2_Duplicate ........................................................................................................................... 77
+TPM2_Rewrap .............................................................................................................................. 81
+TPM2_Import ................................................................................................................................ 86
+
+Asymmetric Primitives ......................................................................................................................... 92
+
+16.1
+16.2
+16.3
+16.4
+16.5
+16.6
+16.7
+17
+
+TPM2_Create................................................................................................................................ 46
+TPM2_Load .................................................................................................................................. 51
+TPM2_LoadExternal ..................................................................................................................... 55
+TPM2_ReadPublic ........................................................................................................................ 60
+TPM2_ActivateCredential ............................................................................................................. 63
+TPM2_MakeCredential ................................................................................................................. 67
+TPM2_Unseal ............................................................................................................................... 70
+TPM2_ObjectChangeAuth ............................................................................................................ 73
+
+Duplication Commands ....................................................................................................................... 77
+
+15.1
+15.2
+15.3
+16
+
+Trusted Platform Module Library
+
+Introduction ................................................................................................................................. 151
+TPM2_Certify .............................................................................................................................. 153
+TPM2_CertifyCreation ................................................................................................................ 157
+TPM2_Quote............................................................................................................................... 161
+TPM2_GetSessionAuditDigest ................................................................................................... 165
+TPM2_GetCommandAuditDigest ............................................................................................... 169
+TPM2_GetTime........................................................................................................................... 173
+
+Ephemeral EC Keys .......................................................................................................................... 177
+
+Page iv
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+21.1
+21.2
+21.3
+22
+
+Introduction ................................................................................................................................. 200
+TPM2_PCR_Extend ................................................................................................................... 201
+TPM2_PCR_Event ..................................................................................................................... 204
+TPM2_PCR_Read ...................................................................................................................... 207
+TPM2_PCR_Allocate .................................................................................................................. 210
+TPM2_PCR_SetAuthPolicy ........................................................................................................ 213
+TPM2_PCR_SetAuthValue ......................................................................................................... 216
+TPM2_PCR_Reset ..................................................................................................................... 219
+_TPM_Hash_Start ...................................................................................................................... 222
+_TPM_Hash_Data ...................................................................................................................... 224
+_TPM_Hash_End ....................................................................................................................... 226
+
+Enhanced Authorization (EA) Commands ........................................................................................ 229
+
+25.1
+25.2
+25.3
+25.4
+25.5
+25.6
+25.7
+25.8
+25.9
+25.10
+25.11
+25.12
+25.13
+25.14
+25.15
+25.16
+25.17
+25.18
+25.19
+25.20
+26
+
+Introduction ................................................................................................................................. 195
+TPM2_SetCommandCodeAuditStatus ....................................................................................... 196
+
+Integrity Collection (PCR) .................................................................................................................. 200
+
+24.1
+24.2
+24.3
+24.4
+24.5
+24.6
+24.7
+24.8
+24.9
+24.10
+24.11
+25
+
+TPM2_VerifySignature ................................................................................................................ 187
+TPM2_Sign ................................................................................................................................. 191
+
+Command Audit ................................................................................................................................. 195
+
+23.1
+23.2
+24
+
+Introduction ................................................................................................................................. 177
+TPM2_Commit ............................................................................................................................ 178
+TPM2_EC_Ephemeral ................................................................................................................ 184
+
+Signing and Signature Verification .................................................................................................... 187
+
+22.1
+22.2
+23
+
+Part 3: Commands
+
+Introduction ................................................................................................................................. 229
+Signed Authorization Actions ...................................................................................................... 230
+TPM2_PolicySigned ................................................................................................................... 234
+TPM2_PolicySecret .................................................................................................................... 240
+TPM2_PolicyTicket ..................................................................................................................... 244
+TPM2_PolicyOR ......................................................................................................................... 248
+TPM2_PolicyPCR ....................................................................................................................... 252
+TPM2_PolicyLocality .................................................................................................................. 256
+TPM2_PolicyNV .......................................................................................................................... 260
+TPM2_PolicyCounterTimer......................................................................................................... 265
+TPM2_PolicyCommandCode ..................................................................................................... 270
+TPM2_PolicyPhysicalPresence .................................................................................................. 273
+TPM2_PolicyCpHash .................................................................................................................. 276
+TPM2_PolicyNameHash ............................................................................................................. 280
+TPM2_PolicyDuplicationSelect ................................................................................................... 283
+TPM2_PolicyAuthorize ............................................................................................................... 287
+TPM2_PolicyAuthValue .............................................................................................................. 291
+TPM2_PolicyPassword ............................................................................................................... 294
+TPM2_PolicyGetDigest ............................................................................................................... 297
+TPM2_PolicyNvWritten ............................................................................................................... 300
+
+Hierarchy Commands........................................................................................................................ 304
+
+26.1
+26.2
+26.3
+
+TPM2_CreatePrimary ................................................................................................................. 304
+TPM2_HierarchyControl ............................................................................................................. 308
+TPM2_SetPrimaryPolicy ............................................................................................................. 312
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page v
+October 31, 2013
+
+ Part 3: Commands
+26.4
+26.5
+26.6
+26.7
+26.8
+27
+
+TPM2_ReadClock ....................................................................................................................... 372
+TPM2_ClockSet .......................................................................................................................... 375
+TPM2_ClockRateAdjust .............................................................................................................. 378
+
+Capability Commands ....................................................................................................................... 381
+
+32.1
+32.2
+32.3
+33
+
+Introduction ................................................................................................................................. 354
+TPM2_ContextSave .................................................................................................................... 354
+TPM2_ContextLoad .................................................................................................................... 359
+TPM2_FlushContext ................................................................................................................... 364
+TPM2_EvictControl ..................................................................................................................... 367
+
+Clocks and Timers............................................................................................................................. 372
+
+31.1
+31.2
+31.3
+32
+
+Introduction ................................................................................................................................. 343
+TPM2_FieldUpgradeStart ........................................................................................................... 345
+TPM2_FieldUpgradeData ........................................................................................................... 348
+TPM2_FirmwareRead ................................................................................................................. 351
+
+Context Management ........................................................................................................................ 354
+
+30.1
+30.2
+30.3
+30.4
+30.5
+31
+
+Introduction ................................................................................................................................. 337
+TPM2_PP_Commands ............................................................................................................... 337
+TPM2_SetAlgorithmSet .............................................................................................................. 340
+
+Field Upgrade .................................................................................................................................... 343
+
+29.1
+29.2
+29.3
+29.4
+30
+
+Introduction ................................................................................................................................. 331
+TPM2_DictionaryAttackLockReset ............................................................................................. 331
+TPM2_DictionaryAttackParameters............................................................................................ 334
+
+Miscellaneous Management Functions ............................................................................................. 337
+
+28.1
+28.2
+28.3
+29
+
+TPM2_ChangePPS .................................................................................................................... 315
+TPM2_ChangeEPS .................................................................................................................... 318
+TPM2_Clear ................................................................................................................................ 321
+TPM2_ClearControl .................................................................................................................... 325
+TPM2_HierarchyChangeAuth ..................................................................................................... 328
+
+Dictionary Attack Functions ............................................................................................................... 331
+
+27.1
+27.2
+27.3
+28
+
+Trusted Platform Module Library
+
+Introduction ................................................................................................................................. 381
+TPM2_GetCapability ................................................................................................................... 381
+TPM2_TestParms ....................................................................................................................... 389
+
+Non-volatile Storage .......................................................................................................................... 392
+
+33.1
+33.2
+33.3
+33.4
+33.5
+33.6
+33.7
+33.8
+33.9
+33.10
+33.11
+
+Introduction ................................................................................................................................. 392
+NV Counters ............................................................................................................................... 393
+TPM2_NV_DefineSpace ............................................................................................................. 394
+TPM2_NV_UndefineSpace ......................................................................................................... 400
+TPM2_NV_UndefineSpaceSpecial ............................................................................................. 403
+TPM2_NV_ReadPublic ............................................................................................................... 406
+TPM2_NV_Write ......................................................................................................................... 409
+TPM2_NV_Increment ................................................................................................................. 413
+TPM2_NV_Extend ...................................................................................................................... 417
+TPM2_NV_SetBits ...................................................................................................................... 421
+TPM2_NV_WriteLock ................................................................................................................. 425
+
+Page vi
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+33.12
+33.13
+33.14
+33.15
+33.16
+
+Part 3: Commands
+
+TPM2_NV_GlobalWriteLock ....................................................................................................... 429
+TPM2_NV_Read ......................................................................................................................... 432
+TPM2_NV_ReadLock ................................................................................................................. 435
+TPM2_NV_ChangeAuth ............................................................................................................. 438
+TPM2_NV_Certify ....................................................................................................................... 441
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page vii
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Tables
+Table 1 — Command Modifiers and Decoration ........................................................................................... 2
+Table 2 — Separators ................................................................................................................................... 3
+Table 3 — Unmarshaling Errors ................................................................................................................. 10
+Table 4 — Command-Independent Response Codes ................................................................................ 13
+Table 5 — TPM2_Startup Command .......................................................................................................... 21
+Table 6 — TPM2_Startup Response .......................................................................................................... 21
+Table 7 — TPM2_Shutdown Command ..................................................................................................... 25
+Table 8 — TPM2_Shutdown Response ...................................................................................................... 25
+Table 9 — TPM2_SelfTest Command ........................................................................................................ 30
+Table 10 — TPM2_SelfTest Response ...................................................................................................... 30
+Table 11 — TPM2_IncrementalSelfTest Command ................................................................................... 33
+Table 12 — TPM2_IncrementalSelfTest Response ................................................................................... 33
+Table 13 — TPM2_GetTestResult Command ............................................................................................ 36
+Table 14 — TPM2_GetTestResult Response............................................................................................. 36
+Table 15 — TPM2_StartAuthSession Command ....................................................................................... 40
+Table 16 — TPM2_StartAuthSession Response ........................................................................................ 40
+Table 17 — TPM2_PolicyRestart Command .............................................................................................. 44
+Table 18 — TPM2_PolicyRestart Response .............................................................................................. 44
+Table 19 — TPM2_Create Command ........................................................................................................ 48
+Table 20 — TPM2_Create Response ......................................................................................................... 48
+Table 21 — TPM2_Load Command ........................................................................................................... 52
+Table 22 — TPM2_Load Response ............................................................................................................ 52
+Table 23 — TPM2_LoadExternal Command .............................................................................................. 57
+Table 24 — TPM2_LoadExternal Response .............................................................................................. 57
+Table 25 — TPM2_ReadPublic Command ................................................................................................. 61
+Table 26 — TPM2_ReadPublic Response ................................................................................................. 61
+Table 27 — TPM2_ActivateCredential Command ...................................................................................... 64
+Table 28 — TPM2_ActivateCredential Response ...................................................................................... 64
+Table 29 — TPM2_MakeCredential Command .......................................................................................... 68
+Table 30 — TPM2_MakeCredential Response .......................................................................................... 68
+Table 31 — TPM2_Unseal Command ........................................................................................................ 71
+Table 32 — TPM2_Unseal Response ........................................................................................................ 71
+Table 33 — TPM2_ObjectChangeAuth Command ..................................................................................... 74
+Table 34 — TPM2_ObjectChangeAuth Response ..................................................................................... 74
+Table 35 — TPM2_Duplicate Command .................................................................................................... 78
+Table 36 — TPM2_Duplicate Response ..................................................................................................... 78
+Table 37 — TPM2_Rewrap Command ....................................................................................................... 82
+Table 38 — TPM2_Rewrap Response ....................................................................................................... 82
+Page viii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 39 — TPM2_Import Command ......................................................................................................... 88
+Table 40 — TPM2_Import Response ......................................................................................................... 88
+Table 41 — Padding Scheme Selection ..................................................................................................... 92
+Table 42 — Message Size Limits Based on Padding ................................................................................. 93
+Table 43 — TPM2_RSA_Encrypt Command.............................................................................................. 94
+Table 44 — TPM2_RSA_Encrypt Response .............................................................................................. 94
+Table 45 — TPM2_RSA_Decrypt Command ............................................................................................. 98
+Table 46 — TPM2_RSA_Decrypt Response .............................................................................................. 98
+Table 47 — TPM2_ECDH_KeyGen Command ........................................................................................ 102
+Table 48 — TPM2_ECDH_KeyGen Response ........................................................................................ 102
+Table 49 — TPM2_ECDH_ZGen Command ............................................................................................ 105
+Table 50 — TPM2_ECDH_ZGen Response ............................................................................................ 105
+Table 51 — TPM2_ECC_Parameters Command ..................................................................................... 107
+Table 52 — TPM2_ECC_Parameters Response ..................................................................................... 107
+Table 53 — TPM2_ZGen_2Phase Command .......................................................................................... 110
+Table 54 — TPM2_ZGen_2Phase Response .......................................................................................... 110
+Table 55 — Symmetric Chaining Process ................................................................................................ 114
+Table 56 — TPM2_EncryptDecrypt Command......................................................................................... 116
+Table 57 — TPM2_EncryptDecrypt Response ......................................................................................... 116
+Table 58 — TPM2_Hash Command ......................................................................................................... 120
+Table 59 — TPM2_Hash Response ......................................................................................................... 120
+Table 60 — TPM2_HMAC Command ....................................................................................................... 123
+Table 61 — TPM2_HMAC Response ....................................................................................................... 123
+Table 62 — TPM2_GetRandom Command .............................................................................................. 127
+Table 63 — TPM2_GetRandom Response .............................................................................................. 127
+Table 64 — TPM2_StirRandom Command .............................................................................................. 130
+Table 65 — TPM2_StirRandom Response ............................................................................................... 130
+Table 66 — Hash Selection Matrix ........................................................................................................... 132
+Table 67 — TPM2_HMAC_Start Command ............................................................................................. 133
+Table 68 — TPM2_HMAC_Start Response ............................................................................................. 133
+Table 69 — TPM2_HashSequenceStart Command ................................................................................. 137
+Table 70 — TPM2_HashSequenceStart Response ................................................................................. 137
+Table 71 — TPM2_SequenceUpdate Command ..................................................................................... 140
+Table 72 — TPM2_SequenceUpdate Response ...................................................................................... 140
+Table 73 — TPM2_SequenceComplete Command ................................................................................. 144
+Table 74 — TPM2_SequenceComplete Response .................................................................................. 144
+Table 75 — TPM2_EventSequenceComplete Command ........................................................................ 148
+Table 76 — TPM2_EventSequenceComplete Response ......................................................................... 148
+Table 77 — TPM2_Certify Command ....................................................................................................... 154
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page ix
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Table 78 — TPM2_Certify Response ....................................................................................................... 154
+Table 79 — TPM2_CertifyCreation Command ......................................................................................... 158
+Table 80 — TPM2_CertifyCreation Response .......................................................................................... 158
+Table 81 — TPM2_Quote Command ....................................................................................................... 162
+Table 82 — TPM2_Quote Response ........................................................................................................ 162
+Table 83 — TPM2_GetSessionAuditDigest Command ............................................................................ 166
+Table 84 — TPM2_GetSessionAuditDigest Response ............................................................................ 166
+Table 85 — TPM2_GetCommandAuditDigest Command ........................................................................ 170
+Table 86 — TPM2_GetCommandAuditDigest Response ......................................................................... 170
+Table 87 — TPM2_GetTime Command ................................................................................................... 174
+Table 88 — TPM2_GetTime Response .................................................................................................... 174
+Table 89 — TPM2_Commit Command ..................................................................................................... 180
+Table 90 — TPM2_Commit Response ..................................................................................................... 180
+Table 91 — TPM2_EC_Ephemeral Command ......................................................................................... 185
+Table 92 — TPM2_EC_Ephemeral Response ......................................................................................... 185
+Table 93 — TPM2_VerifySignature Command......................................................................................... 188
+Table 94 — TPM2_VerifySignature Response ......................................................................................... 188
+Table 95 — TPM2_Sign Command .......................................................................................................... 192
+Table 96 — TPM2_Sign Response .......................................................................................................... 192
+Table 97 — TPM2_SetCommandCodeAuditStatus Command ................................................................ 197
+Table 98 — TPM2_SetCommandCodeAuditStatus Response ................................................................ 197
+Table 99 — TPM2_PCR_Extend Command ............................................................................................ 202
+Table 100 — TPM2_PCR_Extend Response ........................................................................................... 202
+Table 101 — TPM2_PCR_Event Command ............................................................................................ 205
+Table 102 — TPM2_PCR_Event Response ............................................................................................. 205
+Table 103 — TPM2_PCR_Read Command ............................................................................................. 208
+Table 104 — TPM2_PCR_Read Response ............................................................................................. 208
+Table 105 — TPM2_PCR_Allocate Command ......................................................................................... 211
+Table 106 — TPM2_PCR_Allocate Response ......................................................................................... 211
+Table 107 — TPM2_PCR_SetAuthPolicy Command ............................................................................... 214
+Table 108 — TPM2_PCR_SetAuthPolicy Response ............................................................................... 214
+Table 109 — TPM2_PCR_SetAuthValue Command ............................................................................... 217
+Table 110 — TPM2_PCR_SetAuthValue Response ................................................................................ 217
+Table 111 — TPM2_PCR_Reset Command ............................................................................................ 220
+Table 112 — TPM2_PCR_Reset Response ............................................................................................. 220
+Table 113 — TPM2_PolicySigned Command .......................................................................................... 236
+Table 114 — TPM2_PolicySigned Response ........................................................................................... 236
+Table 115 — TPM2_PolicySecret Command ........................................................................................... 241
+Table 116 — TPM2_PolicySecret Response ............................................................................................ 241
+Page x
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 117 — TPM2_PolicyTicket Command ............................................................................................ 245
+Table 118 — TPM2_PolicyTicket Response ............................................................................................ 245
+Table 119 — TPM2_PolicyOR Command ................................................................................................ 249
+Table 120 — TPM2_PolicyOR Response ................................................................................................. 249
+Table 121 — TPM2_PolicyPCR Command .............................................................................................. 253
+Table 122 — TPM2_PolicyPCR Response .............................................................................................. 253
+Table 123 — TPM2_PolicyLocality Command ......................................................................................... 257
+Table 124 — TPM2_PolicyLocality Response .......................................................................................... 257
+Table 125 — TPM2_PolicyNV Command ................................................................................................. 261
+Table 126 — TPM2_PolicyNV Response ................................................................................................. 261
+Table 127 — TPM2_PolicyCounterTimer Command ............................................................................... 266
+Table 128 — TPM2_PolicyCounterTimer Response ................................................................................ 266
+Table 129 — TPM2_PolicyCommandCode Command ............................................................................ 271
+Table 130 — TPM2_PolicyCommandCode Response ............................................................................. 271
+Table 131 — TPM2_PolicyPhysicalPresence Command ......................................................................... 274
+Table 132 — TPM2_PolicyPhysicalPresence Response ......................................................................... 274
+Table 133 — TPM2_PolicyCpHash Command......................................................................................... 277
+Table 134 — TPM2_PolicyCpHash Response ......................................................................................... 277
+Table 135 — TPM2_PolicyNameHash Command.................................................................................... 281
+Table 136 — TPM2_PolicyNameHash Response .................................................................................... 281
+Table 137 — TPM2_PolicyDuplicationSelect Command .......................................................................... 284
+Table 138 — TPM2_PolicyDuplicationSelect Response .......................................................................... 284
+Table 139 — TPM2_PolicyAuthorize Command ...................................................................................... 288
+Table 140 — TPM2_PolicyAuthorize Response ....................................................................................... 288
+Table 141 — TPM2_PolicyAuthValue Command ..................................................................................... 292
+Table 142 — TPM2_PolicyAuthValue Response ..................................................................................... 292
+Table 143 — TPM2_PolicyPassword Command ...................................................................................... 295
+Table 144 — TPM2_PolicyPassword Response ...................................................................................... 295
+Table 145 — TPM2_PolicyGetDigest Command...................................................................................... 298
+Table 146 — TPM2_PolicyGetDigest Response ...................................................................................... 298
+Table 133 — TPM2_PolicyNvWritten Command ...................................................................................... 301
+Table 134 — TPM2_PolicyNvWritten Response ...................................................................................... 301
+Table 147 — TPM2_CreatePrimary Command ........................................................................................ 305
+Table 148 — TPM2_CreatePrimary Response ........................................................................................ 305
+Table 149 — TPM2_HierarchyControl Command .................................................................................... 309
+Table 150 — TPM2_HierarchyControl Response .................................................................................... 309
+Table 151 — TPM2_SetPrimaryPolicy Command .................................................................................... 313
+Table 152 — TPM2_SetPrimaryPolicy Response .................................................................................... 313
+Table 153 — TPM2_ChangePPS Command ........................................................................................... 316
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xi
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Table 154 — TPM2_ChangePPS Response ............................................................................................ 316
+Table 155 — TPM2_ChangeEPS Command ........................................................................................... 319
+Table 156 — TPM2_ChangeEPS Response ............................................................................................ 319
+Table 157 — TPM2_Clear Command ....................................................................................................... 322
+Table 158 — TPM2_Clear Response ....................................................................................................... 322
+Table 159 — TPM2_ClearControl Command ........................................................................................... 326
+Table 160 — TPM2_ClearControl Response ........................................................................................... 326
+Table 161 — TPM2_HierarchyChangeAuth Command ............................................................................ 329
+Table 162 — TPM2_HierarchyChangeAuth Response ............................................................................ 329
+Table 163 — TPM2_DictionaryAttackLockReset Command .................................................................... 332
+Table 164 — TPM2_DictionaryAttackLockReset Response .................................................................... 332
+Table 165 — TPM2_DictionaryAttackParameters Command .................................................................. 335
+Table 166 — TPM2_DictionaryAttackParameters Response ................................................................... 335
+Table 167 — TPM2_PP_Commands Command ...................................................................................... 338
+Table 168 — TPM2_PP_Commands Response ...................................................................................... 338
+Table 169 — TPM2_SetAlgorithmSet Command ..................................................................................... 341
+Table 170 — TPM2_SetAlgorithmSet Response...................................................................................... 341
+Table 171 — TPM2_FieldUpgradeStart Command .................................................................................. 346
+Table 172 — TPM2_FieldUpgradeStart Response .................................................................................. 346
+Table 173 — TPM2_FieldUpgradeData Command .................................................................................. 349
+Table 174 — TPM2_FieldUpgradeData Response .................................................................................. 349
+Table 175 — TPM2_FirmwareRead Command........................................................................................ 352
+Table 176 — TPM2_FirmwareRead Response ........................................................................................ 352
+Table 177 — TPM2_ContextSave Command........................................................................................... 355
+Table 178 — TPM2_ContextSave Response ........................................................................................... 355
+Table 179 — TPM2_ContextLoad Command ........................................................................................... 360
+Table 180 — TPM2_ContextLoad Response ........................................................................................... 360
+Table 181 — TPM2_FlushContext Command .......................................................................................... 365
+Table 182 — TPM2_FlushContext Response .......................................................................................... 365
+Table 183 — TPM2_EvictControl Command ............................................................................................ 369
+Table 184 — TPM2_EvictControl Response ............................................................................................ 369
+Table 185 — TPM2_ReadClock Command.............................................................................................. 373
+Table 186 — TPM2_ReadClock Response .............................................................................................. 373
+Table 187 — TPM2_ClockSet Command ................................................................................................. 376
+Table 188 — TPM2_ClockSet Response ................................................................................................. 376
+Table 189 — TPM2_ClockRateAdjust Command..................................................................................... 379
+Table 190 — TPM2_ClockRateAdjust Response ..................................................................................... 379
+Table 191 — TPM2_GetCapability Command.......................................................................................... 385
+Table 192 — TPM2_GetCapability Response .......................................................................................... 385
+Page xii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 193 — TPM2_TestParms Command .............................................................................................. 390
+Table 194 — TPM2_TestParms Response .............................................................................................. 390
+Table 195 — TPM2_NV_DefineSpace Command ................................................................................... 396
+Table 196 — TPM2_NV_DefineSpace Response .................................................................................... 396
+Table 197 — TPM2_NV_UndefineSpace Command ............................................................................... 401
+Table 198 — TPM2_NV_UndefineSpace Response ................................................................................ 401
+Table 199 — TPM2_NV_UndefineSpaceSpecial Command .................................................................... 404
+Table 200 — TPM2_NV_UndefineSpaceSpecial Response .................................................................... 404
+Table 201 — TPM2_NV_ReadPublic Command ...................................................................................... 407
+Table 202 — TPM2_NV_ReadPublic Response ...................................................................................... 407
+Table 203 — TPM2_NV_Write Command ................................................................................................ 410
+Table 204 — TPM2_NV_Write Response ................................................................................................ 410
+Table 205 — TPM2_NV_Increment Command ........................................................................................ 414
+Table 206 — TPM2_NV_Increment Response......................................................................................... 414
+Table 207 — TPM2_NV_Extend Command ............................................................................................. 418
+Table 208 — TPM2_NV_Extend Response ............................................................................................. 418
+Table 209 — TPM2_NV_SetBits Command ............................................................................................. 422
+Table 210 — TPM2_NV_SetBits Response ............................................................................................. 422
+Table 211 — TPM2_NV_WriteLock Command ........................................................................................ 426
+Table 212 — TPM2_NV_WriteLock Response......................................................................................... 426
+Table 213 — TPM2_NV_GlobalWriteLock Command .............................................................................. 430
+Table 214 — TPM2_NV_GlobalWriteLock Response .............................................................................. 430
+Table 215 — TPM2_NV_Read Command................................................................................................ 433
+Table 216 — TPM2_NV_Read Response ................................................................................................ 433
+Table 217 — TPM2_NV_ReadLock Command ........................................................................................ 436
+Table 218 — TPM2_NV_ReadLock Response ........................................................................................ 436
+Table 219 — TPM2_NV_ChangeAuth Command .................................................................................... 439
+Table 220 — TPM2_NV_ChangeAuth Response .................................................................................... 439
+Table 221 — TPM2_NV_Certify Command .............................................................................................. 442
+Table 222 — TPM2_NV_Certify Response .............................................................................................. 442
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xiii
+October 31, 2013
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Trusted Platform Module Library
+Part 3: Commands
+1
+
+Scope
+
+This part 3 of the Trusted Module Library specification contains the definitions of the TPM commands.
+These commands make use of the constants, flags, structure, and union definitions defined in part 2:
+Structures.
+The detailed description of the operation of the commands is written in the C language with extensive
+comments. The behavior of the C code in this part 3 is normative but does not fully describe the behavior
+of a TPM. The combination of this part 3 and part 4: Supporting Routines is sufficient to fully describe the
+required behavior of a TPM.
+The code in parts 3 and 4 is written to define the behavior of a compliant TPM. In some cases (e.g.,
+firmware update), it is not possible to provide a compliant implementation. In those cases, any
+implementation provided by the vendor that meets the general description of the function provided in part
+3 would be compliant.
+The code in parts 3 and 4 is not written to meet any particular level of conformance nor does this
+specification require that a TPM meet any particular level of conformance.
+2
+
+Terms and Definitions
+
+For the purposes of this document, the terms and definitions given in part 1 of this specification apply.
+3
+
+Symbols and abbreviated terms
+
+For the purposes of this document, the symbols and abbreviated terms given in part 1 apply.
+4
+
+Notation
+
+4.1 Introduction
+In addition to the notation in this clause, the “Notations” clause in Part 1 of this specification is applicable
+to this Part 3.
+Command and response tables used various decorations to indicate the fields of the command and the
+allowed types. These decorations are described in this clause.
+4.2
+
+Table Decorations
+
+The symbols and terms in the Notation column of Table 1 are used in the tables for the command
+schematics. These values indicate various qualifiers for the parameters or descriptions with which they
+are associated.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 1
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+Table 1 — Command Modifiers and Decoration
+
+Notation
+
+Meaning
+
++
+
+A Type decoration – When appended to a value in the Type column of a command, this symbol
+indicates that the parameter is allowed to use the “null” value of the data type (see "Conditional
+Types" in Part 2). The null value is usually TPM_RH_NULL for a handle or TPM_ALG_NULL for
+an algorithm selector.
+
+@
+
+A Name decoration – When this symbol precedes a handle parameter in the “Name” column, it
+indicates that an authorization session is required for use of the entity associated with the handle.
+If a handle does not have this symbol, then an authorization session is not allowed.
+
++PP
+
+A Description modifier – This modifier may follow TPM_RH_PLATFORM in the “Description”
+column to indicate that Physical Presence is required when platformAuth/platformPolicy is
+provided.
+
++{PP}
+
+A Description modifier – This modifier may follow TPM_RH_PLATFORM to indicate that Physical
+Presence may be required when platformAuth/platformPolicy is provided. The commands with this
+notation may be in the setList or clearList of TPM2_PP_Commands().
+
+{NV}
+
+A Description modifier – This modifier may follow the commandCode in the “Description” column
+to indicate that the command may result in an update of NV memory and be subject to rate
+throttling by the TPM. If the command code does not have this notation, then a write to NV
+memory does not occur as part of the command actions.
+NOTE Any command that uses authorization may cause a write to NV if there is an authorization
+failure. A TPM may use the occasion of command execution to update the NV
+copy of clock.
+
+{F}
+
+A Description modifier – This modifier indicates that the “flushed” attribute will be SET in the
+TPMA_CC for the command. The modifier may follow the commandCode in the “Description”
+column to indicate that any transient handle context used by the command will be flushed from the
+TPM when the command completes. This may be combined with the {NV} modifier but not with the
+{E} modifier.
+EXAMPLE 1
+
+{E}
+
+{NV F}
+
+EXAMPLE 2
+
+TPM2_SequenceComplete() will flush the context associated with the sequenceHandle.
+
+A Description modifier – This modifier indicates that the “extensive” attribute will be SET in the
+TPMA_CC for the command. This modifier may follow the commandCode in the “Description”
+column to indicate that the command may flush many objects and re-enumeration of the loaded
+context likely will be required. This may be combined with the {NV} modifier but not with the {F}
+modifier.
+EXAMPLE 1
+
+Auth Index:
+
+{NV E}
+
+EXAMPLE 2
+
+TPM2_Clear() will flush all contexts associated with the Storage hierarchy and the
+Endorsement hierarchy.
+
+A Description modifier – When a handle has a “@” decoration, the “Description” column will
+contain an “Auth Index:” entry for the handle. This entry indicates the number of the authorization
+session. The authorization sessions associated with handles will occur in the session area in the
+order of the handles with the “@” modifier. Sessions used only for encryption/decryption or only for
+audit will follow the handles used for authorization.
+
+Page 2
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Notation
+
+Meaning
+
+Auth Role:
+
+A Description modifier – This will be in the “Description” column of a handle with the “@”
+decoration. It may have a value of USER, ADMIN or DUP. If the handle has the Auth Role of
+USER and the handle is an Object, the type of authorization is determined by the setting of
+userWithAuth in the Object's attributes. If the Auth Role is ADMIN and the handle is an Object, the
+type of authorization is determined by the setting of adminWithPolicy in the Object's attributes. If
+the DUP role is selected, authorization may only be with a policy session (DUP role only applies to
+Objects). When either ADMIN or DUP role is selected, a policy command that selects the
+command being authorized is required to be part of the policy.
+EXAMPLE
+
+TPM2_Certify requires the ADMIN role for the first handle (objectHandle). The policy authorization
+for objectHandle is required to contain TPM2_PolicyCommandCode(commandCode ==
+TPM_CC_Certify). This sets the state of the policy so that it can be used for ADMIN role
+authorization in TPM2_Certify().
+
+If the handle references an NV Index, then the allowed authorizations are determined by the
+settings of the attributes of the NV Index as described in Part 2, "TPMA_NV (NV Index Attributes)."
+
+4.3
+
+Handle and Parameter Demarcation
+
+The demarcations between the header, handle, and parameter parts are indicated by:
+Table 2 — Separators
+Separator
+
+Meaning
+the values immediately following are in the handle area
+the values immediately following are in the parameter area
+
+4.4
+
+AuthorizationSize and ParameterSize
+
+Authorization sessions are not shown in the command or response schematics. When the tag of a
+command or response is TPM_ST_SESSIONS, then a 32-bit value will be present in the
+command/response buffer to indicate the size of the authorization field or the parameter field. This value
+shall immediately follow the handle area (which may contain no handles). For a command, this value
+(authorizationSize) indicates the size of the Authorization Area and shall have a value of 9 or more. For a
+response, this value (parameterSize) indicates the size of the parameter area and may have a value of
+zero.
+If the authorizationSize field is present in the command, parameterSize will be present in the response,
+but only if the responseCode is TPM_RC_SUCCESS.
+When the command tag is TPM_ST_NO_SESSIONS, no authorizations are present and no
+authorizationSize field is required and shall not be present.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 3
+October 31, 2013
+
+ Part 3: Commands
+
+5
+
+Trusted Platform Module Library
+
+Normative References
+
+The “Normative References” clause in Part 1 of this specification is applicable to this Part 3.
+6
+
+Symbols and Abbreviated Terms
+
+The “Symbols and Abbreviated Terms” clause in Part 1 of this specification is applicable to this Part 3.
+
+7
+7.1
+
+Command Processing
+Introduction
+
+This clause defines the command validations that are required of any implementation and the response
+code returned if the indicated check fails. Unless stated otherwise, the order of the checks is not
+normative and different TPM may give different responses when a command has multiple errors.
+In the description below, some statements that describe a check may be followed by a response code in
+parentheses. This is the normative response code should the indicated check fail. A normative response
+code may also be included in the statement.
+7.2
+
+Command Header Validation
+
+Before a TPM may begin the actions associated with a command, a set of command format and
+consistency checks shall be performed. These checks are listed below and should be performed in the
+indicated order.
+a) The TPM shall successfully unmarshal a TPMI_ST_COMMAND_TAG and verify that it is either
+TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS (TPM_RC_BAD_TAG).
+b) The TPM shall successfully unmarshal a UINT32 as the commandSize. If the TPM has an interface
+buffer that is loaded by some hardware process, the number of octets in the input buffer for the
+command reported by the hardware process shall exactly match the value in commandSize
+(TPM_RC_COMMAND_SIZE).
+NOTE
+
+A TPM may have direct access to system memory and unmarshal directly from that memory.
+
+c) The TPM shall successfully unmarshal a TPM_CC and verify that the command is implemented
+(TPM_RC_COMMAND_CODE).
+7.3
+
+Mode Checks
+
+The following mode checks shall be performed in the order listed:
+
+Page 4
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+a) If the TPM is in Failure mode, then the commandCode is TPM_CC_GetTestResult or
+TPM_CC_GetCapability (TPM_RC_FAILURE) and the command tag is TPM_ST_NO_SESSIONS
+(TPM_RC_FAILURE).
+NOTE 1
+
+In Failure mode, the TPM has no cryptographic capability and proc essing of sessions is not
+supported.
+
+b) The TPM is in Field Upgrade mode (FUM), the commandCode is TPM_CC_FieldUpgradeData
+(TPM_RC_UPGRADE).
+c) If the TPM has not been initialized (TPM2_Startup()), then the commandCode is TPM_CC_Startup
+(TPM_RC_INITIALIZE).
+NOTE 2
+
+The TPM may enter Failure mode during _TPM_Init processing, before TPM2_Startup(). Since
+the platform firmware cannot know that the TPM is in Failure mode without accessing it, and
+since the first command is required to be TPM2_Startup(), the expected sequence will be that
+platform firmware (the CRTM) will issue TPM2_Startup() and receive TPM_RC_FAILURE
+indicating that the TPM is in Failure mode.
+There may be failures where a TPM cannot record that it received TPM2_Startup(). In those
+cases, a TPM in failure mode may process TPM2_GetTestResult(), TPM2_GetCapability(), or
+the field upgrade commands. As a side effect, that TPM may process TPM2_GetTestResult(),
+TPM2_GetCapability() or the field upgrade commands before TPM2_Startup().
+This is a corner case exception to the rule that TPM2_Startup() must be the first command.
+
+The mode checks may be performed before or after the command header validation.
+7.4 Handle Area Validation
+After successfully unmarshaling and validating the command header, the TPM shall perform the following
+checks on the handles and sessions. These checks may be performed in any order.
+a) The TPM shall successfully unmarshal the number of handles required by the command and validate
+that the value of the handle is consistent with the command syntax. If not, the TPM shall return
+TPM_RC_VALUE.
+NOTE 1
+
+The TPM may unmarshal a handle and validate that it references an entity on the TPM before
+unmarshaling a subsequent handle.
+
+NOTE 2
+
+If the submitted command contains fewer handles than required by the syntax of the command,
+the TPM may continue to read into the next area and attempt to interpret the data as a handle.
+
+b) For all handles in the handle area of the command, the TPM will validate that the referenced entity is
+present in the TPM.
+1) If the handle references a transient object, the handle shall reference a loaded object
+(TPM_RC_REFERENCE_H0 + N where N is the number of the handle in the command).
+NOTE 3
+
+If the hierarchy for a transient object is disabled, then the transient objects will be flushe d so this
+check will fail.
+
+2) If the handle references a persistent object, then
+i)
+
+the handle shall reference a persistent object that is currently in TPM non-volatile memory
+(TPM_RC_HANDLE);
+
+ii)
+
+the hierarchy associated with the object is not disabled (TPM_RC_HIERARCHY); and
+
+iii) if the TPM implementation moves a persistent object to RAM for command processing then
+sufficient RAM space is available (TPM_RC_OBJECT_MEMORY).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 5
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+3) If the handle references an NV Index, then
+i)
+
+an Index exists that corresponds to the handle (TPM_RC_HANDLE); and
+
+ii)
+
+the hierarchy associated with the existing NV Index is not disabled (TPM_RC_HANDLE).
+
+iii) the hierarchy associated
+(TPM_RC_HIERARCHY)
+
+with
+
+an
+
+NV
+
+index
+
+being
+
+defined
+
+is
+
+not
+
+disabled
+
+4) If the handle references a session, then the session context shall be present in TPM memory
+(TPM_RC_REFERENCE_S0 + N).
+5) If the handle references a primary seed for a hierarchy (TPM_RH_ENDORSEMENT,
+TPM_RH_OWNER, or TPM_RH_PLATFORM) then the enable for the hierarchy is SET
+(TPM_RC_HIERARCHY).
+6) If the handle references a PCR, then the value is within the range of PCR supported by the TPM
+(TPM_RC_VALUE)
+NOTE 4
+
+7.5
+
+In the reference implementation, this TPM_RC_VALUE is returned by the unmarshaling code for
+a TPMI_DH_PCR.
+
+Session Area Validation
+
+a) If the tag is TPM_ST_SESSIONS and the command is a context management command
+(TPM2_ContextSave(), TPM2_ContextLoad(), or TPM2_FlushContext()) the TPM will return
+TPM_RC_AUTH_CONTEXT.
+b) If the tag is TPM_ST_SESSIONS, the TPM will attempt to unmarshal an authorizationSize and return
+TPM_RC_AUTHSIZE if the value is not within an acceptable range.
+1) The minimum value is (sizeof(TPM_HANDLE) + sizeof(UINT16) + sizeof(TPMA_SESSION) +
+sizeof(UINT16)).
+2) The maximum value of authorizationSize is equal to commandSize – (sizeof(TPM_ST) +
+sizeof(UINT32) + sizeof(TPM_CC) + (N * sizeof(TPM_HANDLE)) + sizeof(UINT32)) where N is
+the number of handles associated with the commandCode and may be zero.
+NOTE 1
+
+(sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_CC)) is the size of a command header. The
+last UINT32 contains the authorizationSize octets, which are not counted as being in the
+authorization session area.
+
+c) The TPM will unmarshal the authorization sessions and perform the following validations:
+1) If the session handle is not a handle for an HMAC session, a handle for a policy session, or,
+TPM_RS_PW then the TPM shall return TPM_RC_HANDLE.
+2) If the session is not loaded, the TPM will return the warning TPM_RC_REFERENCE_S0 + N
+where N is the number of the session. The first session is session zero, N = 0.
+NOTE 2
+
+If the HMAC and policy session contexts use the same memory, the type of the context must
+match the type of the handle.
+
+3) If the maximum allowed number of sessions have been unmarshaled and fewer octets than
+indicated in authorizationSize were unmarshaled (that is, authorizationSize is too large), the TPM
+shall return TPM_RC_AUTHSIZE.
+
+Page 6
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+4) The consistency of the authorization session attributes is checked.
+i)
+
+An authorization session is present for each of the handles with the “@” decoration
+(TPM_RC_AUTH_MISSING).
+
+ii)
+
+Only one session is allowed for:
+(a) session auditing (TPM_RC_ATTRIBUTES) – this session may be used for encrypt or
+decrypt but may not be a session that is also used for authorization;
+(b) decrypting a command parameter (TPM_RC_ATTRIBUTES) – this may be any of the
+authorization sessions, or the audit session, or a session may be added for the single
+purpose of decrypting a command parameter, as long as the total number of sessions
+does not exceed three; and
+(c) encrypting a response parameter (TPM_RC_ATTRIBUTES) – this may be any of the
+authorization sessions, or the audit session if present, ora session may be added for the
+single purpose of encrypting a response parameter, as long as the total number of
+sessions does not exceed three.
+NOTE 3
+
+7.6
+
+A session used for decrypting a command parameter may also be used for
+encrypting a response parameter.
+
+Authorization Checks
+
+After unmarshaling and validating the handles and the consistency of the authorization sessions, the
+authorizations shall be checked. Authorization checks only apply to handles if the handle in the command
+schematic has the “@” decoration.
+a) The public and sensitive portions
+(TPM_RC_AUTH_UNAVAILABLE).
+
+of
+
+the
+
+object
+
+shall
+
+be
+
+present
+
+on
+
+the
+
+TPM
+
+b) If the associated handle is TPM_RH_PLATFORM, and the command requires confirmation with
+physical presence, then physical presence is asserted (TPM_RC_PP).
+c) If the object or NV Index is subject to DA protection, and the authorization is with an HMAC or
+password, then the TPM is not in lockout (TPM_RC_LOCKOUT).
+NOTE 1
+
+An object is subject to DA protection if its noDA attribute is CLEAR. An NV Index is subject to
+DA protection if its TPMA_NV_NO_DA attribute is CLEAR.
+
+NOTE 2
+
+An HMAC or password is required in a policy
+TPM2_PolicyAuthValue() or TPM2_PolicyPassword().
+
+session
+
+when
+
+the
+
+policy
+
+contains
+
+d) If the command requires a handle to have DUP role authorization, then the associated authorization
+session is a policy session (TPM_RC_POLICY_FAIL).
+e) If the command requires a handle to have ADMIN role authorization:
+1) If the entity being authorized is an object and its adminWithPolicy attribute is SET, then the
+authorization session is a policy session (TPM_RC_POLICY_FAIL).
+NOTE 3
+
+If adminWithPolicy is CLEAR, then any type of authorization session is allowed .
+
+2) If the entity being authorized is an NV Index, then the associated authorization session is a policy
+session.
+NOTE 4
+
+The only commands that are currently defined that required use of ADMIN role authorization are
+commands that operate on objects and NV Indices.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 7
+October 31, 2013
+
+ Part 3: Commands
+f)
+
+Trusted Platform Module Library
+
+If the command requires a handle to have USER role authorization:
+1) If the entity being authorized is an object and its userWithAuth attribute is CLEAR, then the
+associated authorization session is a policy session (TPM_RC_POLICY_FAIL).
+2) If the entity being authorized is an NV Index;
+i)
+
+if the authorization session is a policy session;
+(a) the TPMA_NV_POLICYWRITE attribute of the NV Index is SET if the command modifies
+the NV Index data (TPM_RC_AUTH_UNAVAILABLE);
+(b) the TPMA_NV_POLICYREAD attribute of the NV Index is SET if the command reads the
+NV Index data (TPM_RC_AUTH_UNAVAILABLE);
+
+ii)
+
+if the authorization is an HMAC session or a password;
+(a) the TPMA_NV_AUTHWRITE attribute of the NV Index is SET if the command modifies
+the NV Index data (TPM_RC_AUTH_UNAVAILABLE);
+(b) the TPMA_NV_AUTHREAD attribute of the NV Index is SET if the command reads the
+NV Index data (TPM_RC_AUTH_UNAVAILABLE).
+
+g) If the authorization is provided by a policy session, then:
+1) if policySession→timeOut
+(TPM_RC_EXPIRED);
+
+has
+
+been
+
+set,
+
+the
+
+session
+
+shall
+
+not
+
+have
+
+expired
+
+2) if policySession→cpHash has been set, it shall match the cpHash of the command
+(TPM_RC_POLICY_FAIL);
+3) if policySession→commandCode has been set, then commandCode of the command shall match
+(TPM_RC_POLICY_CC);
+4) policySession→policyDigest
+(TPM_RC_POLICY_FAIL);
+
+shall
+
+match
+
+the
+
+authPolicy
+
+associated
+
+with
+
+the
+
+handle
+
+5) if policySession→pcrUpdateCounter has been set, then it shall match the value of
+pcrUpdateCounter (TPM_RC_PCR_CHANGED);
+6) if policySession->commandLocality has been set, it shall match the locality of the command
+(TPM_RC_LOCALITY), and
+7) if the authorization uses an HMAC, then the HMAC is properly constructed using the authValue
+associated with the handle and/or the session secret (TPM_RC_AUTH_FAIL or
+TPM_RC_BAD_AUTH).
+NOTE 5
+
+For a bound session, if the handle references the object us ed to initiate the session, then the
+authValue will not be required but proof of knowledge of the session secret is necessary.
+
+NOTE 6
+
+A policy session may require proof of knowledge of the authValue of the object being authorized.
+
+If the TPM returns an error other than TPM_RC_AUTH_FAIL then the TPM shall not alter any TPM state.
+If the TPM return TPM_RC_AUTH_FAIL, then the TPM shall not alter any TPM state other than
+lockoutCount.
+NOTE 7
+
+7.7
+
+The TPM may decrease failedTries regardless of any other processing performed by the TPM. That
+is, the TPM may exit Lockout mode, regardless of the return code.
+
+Parameter Decryption
+
+If an authorization session has the TPMA_SESSION.decrypt attribute SET, and the command does not
+allow a command parameter to be encrypted, then the TPM will return TPM_RC_ATTRIBUTES.
+
+Page 8
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Otherwise, the TPM will decrypt the parameter using the values associated with the session before
+parsing parameters.
+7.8
+7.8.1
+
+Parameter Unmarshaling
+Introduction
+
+The detailed actions for each command assume that the input parameters of the command have been
+unmarshaled into a command-specific structure with the structure defined by the command schematic.
+Additionally, a response-specific output structure is assumed which will receive the values produced by
+the detailed actions.
+NOTE
+
+An implementation is not required to process parameters in this manner or to separate the
+parameter parsing from the command actions. This method was chosen for the specification so that
+the normative behavior described by the detailed actions would be clear and unencumbered.
+
+Unmarshaling is the process of processing the parameters in the input buffer and preparing the
+parameters for use by the command-specific action code. No data movement need take place but it is
+required that the TPM validate that the parameters meet the requirements of the expected data type as
+defined in Part 2 of this specification.
+7.8.2
+
+Unmarshaling Errors
+
+When an error is encountered while unmarshaling a command parameter, an error response code is
+returned and no command processing occurs. A table defining a data type may have response codes
+embedded in the table to indicate the error returned when the input value does not match the parameters
+of the table.
+NOTE
+
+In the reference implementation, a parameter number is added to the response code so that the
+offending parameter can be isolated. This is optional.
+
+In many cases, the table contains no specific response code value and the return code will be determined
+as defined in Table 3.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 9
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+Table 3 — Unmarshaling Errors
+
+Response Code
+
+Meaning
+
+TPM_RC_ASYMMETRIC
+
+a parameter that should be an asymmetric algorithm selection does not have a
+value that is supported by the TPM
+
+TPM_RC_BAD_TAG
+
+a parameter that should be a command tag selection has a value that is not
+supported by the TPM
+
+TPM_RC_COMMAND_CODE
+
+a parameter that should be a command code does not have a value that is
+supported by the TPM
+
+TPM_RC_HASH
+
+a parameter that should be a hash algorithm selection does not have a value that
+is supported by the TPM
+
+TPM_RC_INSUFFICIENT
+
+the input buffer did not contain enough octets to allow unmarshaling of the
+expected data type;
+
+TPM_RC_KDF
+
+a parameter that should be a key derivation scheme (KDF) selection does not
+have a value that is supported by the TPM
+
+TPM_RC_KEY_SIZE
+
+a parameter that is a key size has a value that is not supported by the TPM
+
+TPM_RC_MODE
+
+a parameter that should be a symmetric encryption mode selection does not have
+a value that is supported by the TPM
+
+TPM_RC_RESERVED
+
+a non-zero value was found in a reserved field of an attribute structure (TPMA_)
+
+TPM_RC_SCHEME
+
+a parameter that should be signing or encryption scheme selection does not have
+a value that is supported by the TPM
+
+TPM_RC_SIZE
+
+the value of a size parameter is larger or smaller than allowed
+
+TPM_RC_SYMMETRIC
+
+a parameter that should be a symmetric algorithm selection does not have a
+value that is supported by the TPM
+
+TPM_RC_TAG
+
+a parameter that should be a structure tag has a value that is not supported by
+the TPM
+
+TPM_RC_TYPE
+
+The type parameter of a TPMT_PUBLIC or TPMT_SENSITIVE has a value that is
+not supported by the TPM
+
+TPM_RC_VALUE
+
+a parameter does not have one of its allowed values
+
+In some commands, a parameter may not be used because of various options of that command.
+However, the unmarshaling code is required to validate that all parameters have values that are allowed
+by the Part 2 definition of the parameter type even if that parameter is not used in the command actions.
+7.9
+
+Command Post Processing
+
+When the code that implements the detailed actions of the command completes, it returns a response
+code. If that code is not TPM_RC_SUCCESS, the post processing code will not update any session or
+audit data and will return a 10-octet response packet.
+If the command completes successfully, the tag of the command determines if any authorization sessions
+will be in the response. If so, the TPM will encrypt the first parameter of the response if indicated by the
+authorization attributes. The TPM will then generate a new nonce value for each session and, if
+appropriate, generate an HMAC.
+
+Page 10
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+NOTE 1
+
+The authorization attributes were validated during the session area validation to ensure that only
+one session was used for parameter encryption of the response and that the command allowed
+encryption in the response.
+
+NOTE 2
+
+No session nonce value is used for a password authorization but the session data is present.
+
+Additionally, if the command is being audited by Command Audit, the audit digest is updated with the
+cpHash of the command and rpHash of the response.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 11
+October 31, 2013
+
+ Part 3: Commands
+
+8
+8.1
+
+Trusted Platform Module Library
+
+Response Values
+Tag
+
+When a command completes successfully, the tag parameter in the response shall have the same value
+as the tag parameter in the command (TPM_ST_SESSIONS or TPM_RC_NO_SESSIONS). When a
+command fails (the responseCode is not TPM_RC_SUCCESS), then the tag parameter in the response
+shall be TPM_ST_NO_SESSIONS.
+A special case exists when the command tag parameter is not an allowed value (TPM_ST_SESSIONS or
+TPM_ST_NO_SESSIONS). For this case, it is assumed that the system software is attempting to send a
+command formatted for a TPM 1.2 but the TPM is not capable of executing TPM 1.2 commands. So that
+the TPM 1.2 compatible software will have a recognizable response, the TPM sets tag to
+TPM_ST_RSP_COMMAND, responseSize to 00 00 00 0A16 and responseCode to TPM_RC_BAD_TAG.
+This is the same response as the TPM 1.2 fatal error for TPM_BADTAG.
+8.2
+
+Response Codes
+
+The normal response for any command is TPM_RC_SUCCESS. Any other value indicates that the
+command did not complete and the state of the TPM is unchanged. An exception to this general rule is
+that the logic associated with dictionary attack protection is allowed to be modified when an authorization
+failure occurs.
+Commands have response codes that are specific to that command, and those response codes are
+enumerated in the detailed actions of each command. The codes associated with the unmarshaling of
+parameters are documented Table 3. Another set of response code value are not command specific and
+indicate a problem that is not specific to the command. That is, if the indicated problem is remedied, the
+same command could be resubmitted and may complete normally.
+The response codes that are not command specific are listed and described in Table 4.
+The reference code for the command actions may have code that generates specific response codes
+associated with a specific check but the listing of responses may not have that response code listed.
+
+Page 12
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Table 4 — Command-Independent Response Codes
+Response Code
+
+Meaning
+
+TPM_RC_CANCELLED
+
+This response code may be returned by a TPM that supports command cancel.
+When the TPM receives an indication that the current command should be
+cancelled, the TPM may complete the command or return this code. If this code
+is returned, then the TPM state is not changed and the same command may be
+retried.
+
+TPM_RC_CONTEXT_GAP
+
+This response code can be returned for commands that manage session
+contexts. It indicates that the gap between the lowest numbered active session
+and the highest numbered session is at the limits of the session tracking logic.
+The remedy is to load the session context with the lowest number so that its
+tracking number can be updated.
+
+TPM_RC_LOCKOUT
+
+This response indicates that authorizations for objects subject to DA protection
+are not allowed at this time because the TPM is in DA lockout mode. The remedy
+is to wait or to exeucte TPM2_DictionaryAttackLockoutReset().
+
+TPM_RC_MEMORY
+
+A TPM may use a common pool of memory for objects, sessions, and other
+purposes. When the TPM does not have enough memory available to perform
+the actions of the command, it may return TPM_RC_MEMORY. This indicates
+that the TPM resource manager may flush either sessions or objects in order to
+make memory available for the command execution. A TPM may choose to
+return TPM_RC_OBJECT_MEMORY or TPM_RC_SESSION_MEMORY if it
+needs contexts of a particular type to be flushed.
+
+TPM_RC_NV_RATE
+
+This response code indicates that the TPM is rate-limiting writes to the NV
+memory in order to prevent wearout. This response is possible for any command
+that explicity writes to NV or commands that incidentally use NV such as a
+command that uses authorization session that may need to update the dictionary
+attack logic.
+
+TPM_RC_NV_UNAVAILABLE
+
+This response code is similar to TPM_RC_NV_RATE but indicates that access to
+NV memory is currently not available and the command is not allowed to proceed
+until it is. This would occur in a system where the NV memory used by the TPM
+is not exclusive to the TPM and is a shared system resource.
+
+TPM_RC_OBJECT_HANDLES
+
+This response code indicates that the TPM has exhausted its handle space and
+no new objects can be loaded unless the TPM is rebooted. This does not occur in
+the reference implementation because of the way that object handles are
+allocated. However, other implementations are allowed to assign each object a
+unique handle each time the object is loaded. A TPM using this implementation
+24
+would be able to load 2 objects before the object space is exhausted.
+
+TPM_RC_OBJECT_MEMORY
+
+This response code can be returned by any command that causes the TPM to
+need an object 'slot'. The most common case where this might be returned is
+when an object is loaded (TPM2_Load, TPM2_CreatePrimary(), or
+TPM2_ContextLoad()). However, the TPM implementation is allowed to use
+object slots for other reasons. In the reference implementation, the TPM copies a
+referenced persistent object into RAM for the duration of the commannd. If all the
+slots are previously occupied, the TPM may return this value. A TPM is allowed
+to use object slots for other purposes and return this value. The remedy when
+this response is returned is for the TPM resource manager to flush a transient
+object.
+
+TPM_RC_REFERENCE_Hx
+
+This response code indicates that a handle in the handle area of the command is
+not associated with a loaded object. The value of 'x' is in the range 0 to 6 with a
+st
+th
+value of 0 indicating the 1 handle and 6 representing the 7 . The TPM resource
+manager needs to find the correct object and load it. It may then adjust the
+handle and retry the command.
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Usually, this error indicates that the TPM resource manager has a corrupted
+database.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 13
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Response Code
+
+Meaning
+
+TPM_RC_REFERENCE_Sx
+
+This response code indicates that a handle in the session area of the command
+is not associated with a loaded session. The value of 'x' is in the range 0 to 6 with
+st
+th
+a value of 0 indicating the 1 session handle and 6 representing the 7 . The
+TPM resource manager needs to find the correct session and load it. It may then
+retry the command.
+NOTE Usually, this error indicates that the TPM resource manager has a
+corrupted database.
+
+TPM_RC_RETRY
+
+the TPM was not able to start the command
+
+This response code indicates that the TPM does not have a handle to assign to a
+new session. This respose is only returned by TPM2_StartAuthSession(). It is
+TPM_RC_SESSION_HANDLES
+listed here because the command is not in error and the TPM resource manager
+can remedy the situation by flushing a session (TPM2_FlushContext().
+
+TPM_RC_SESSION_MEMORY
+
+This response code can be returned by any command that causes the TPM to
+need a session 'slot'. The most common case where this might be returned is
+when a session is loaded (TPM2_StartAuthSession() or TPM2_ContextLoad()).
+However, the TPM implementation is allowed to use object slots for other
+purposes. The remedy when this response is returned is for the TPM resource
+manager to flush a transient object.
+
+TPM_RC_SUCCESS
+
+Normal completion for any command. If the responseCode is
+TPM_RC_SESSIONS, then the rest of the response has the format indicated in
+the response schematic. Otherwise, the response is a 10 octet value indicating
+an error.
+
+TPM_RC_TESTING
+
+This response code indicates that the TPM is performing tests and cannot
+respond to the request at this time. The command may be retried.
+
+TPM_RC_YIELDED
+
+the TPM has suspended operation on the command; forward progress was made
+and the command may be retried.
+See Part 1, “Multi-tasking.”
+NOTE
+
+Page 14
+October 31, 2013
+
+This cannot occur on the reference implementation.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+9
+
+Part 3: Commands
+
+Implementation Dependent
+
+The actions code for each command makes assumptions about the behavior of various sub-systems.
+There are many possible implementations of the subsystems that would achieve equivalent results. The
+actions code is not written to anticipate all possible implementations of the sub-systems. Therefore, it is
+the responsibility of the implementer to ensure that the necessary changes are made to the actions code
+when the sub-system behavior changes.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 15
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Detailed Actions Assumptions
+
+10
+10.1
+
+Introduction
+
+The C code in the Detailed Actions for each command is written with a set of assumptions about the
+processing performed before the action code is called and the processing that will be done after the
+action code completes.
+10.2
+
+Pre-processing
+
+Before calling the command actions code, the following actions have occurred.
+
+
+Verification that the handles in the handle area reference entities that are resident on the TPM.
+NOTE
+
+If a handle is in the parameter portion of the command, the associated entity does not have to
+be loaded, but the handle is required to be the correct type.
+
+
+
+If use of a handle requires authorization, the Password, HMAC, or Policy session associated with the
+handle has been verified.
+
+
+
+If a command parameter was encrypted using parameter encryption, it was decrypted before being
+unmarshaled.
+
+
+
+If the command uses handles or parameters, the calling stack contains a pointer to a data structure
+(in) that holds the unmarshaled values for the handles and commands. If the response has handles
+or parameters, the calling stack contains a pointer to a data structure ( out) to hold the handles and
+parameters generated by the command.
+
+
+
+All parameters of the in structure have been validated and meet the requirements of the parameter
+type as defined in Part 2.
+
+
+
+Space set aside for the out structure is sufficient to hold the largest out structure that could be
+produced by the command
+
+10.3
+
+Post Processing
+
+When the function implementing the command actions completes,
+
+
+response parameters that require parameter encryption will be encrypted after the command actions
+complete;
+
+
+
+audit and session contexts will be updated if the command response is TPM_RC_SUCCESS; and
+
+
+
+the command header and command response parameters will be marshaled to the response buffer.
+
+Page 16
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+11
+
+Part 3: Commands
+
+Start-up
+
+11.1
+
+Introduction
+
+This clause contains the commands used to manage the startup and restart state of a TPM.
+11.2
+
+_TPM_Init
+
+11.2.1 General Description
+_TPM_Init initializes a TPM.
+Initialization actions include testing code required to execute the next expected command. If the TPM is in
+FUM, the next expected command is TPM2_FieldUpgradeData(); otherwise, the next expected command
+is TPM2_Startup().
+NOTE 1
+
+If the TPM performs self-tests after receiving _TPM_Init() and the TPM enters Failure mode before
+receiving TPM2_Startup() or TPM2_FieldUpgradeData(), then the TPM may be able to accept
+TPM2_GetTestResult() or TPM2_GetCapability().
+
+The means of signaling _TPM_Init shall be defined in the platform-specific specifications that define the
+physical interface to the TPM. The platform shall send this indication whenever the platform starts its boot
+process and only when the platform starts its boot process.
+There shall be no software method of generating this indication that does not also reset the platform and
+begin execution of the CRTM.
+NOTE 2
+
+In the reference implementation, this signal causes an internal flag ( s_initialized) to be CLEAR.
+While this flag is CLEAR, the TPM will only accept the next expected command described above.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 17
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+11.2.2 Detailed Actions
+1
+
+#include "InternalRoutines.h"
+
+This function is used to process a _TPM_Init() indication.
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
+void _TPM_Init(void)
+{
+// Initialize crypto engine
+CryptInitUnits();
+// Initialize NV environment
+NvPowerOn();
+// Start clock
+TimePowerOn();
+// Set initialization state
+TPMInit();
+// Set g_DRTMHandle as unassigned
+g_DRTMHandle = TPM_RH_UNASSIGNED;
+// No H-CRTM, yet.
+g_DrtmPreStartup = FALSE;
+return;
+}
+
+Page 18
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+11.3
+
+Part 3: Commands
+
+TPM2_Startup
+
+11.3.1 General Description
+TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that TPM initialization
+is necessary because of a system-wide reset. TPM2_Startup() is only valid after _TPM_Init Additional
+TPM2_Startup() commands are not allowed after it has completed successfully. If a TPM requires
+TPM2_Startup() and another command is received, or if the TPM receives TPM2_Startup() when it is not
+required, the TPM shall return TPM_RC_INITIALIZE.
+NOTE 1
+
+See 11.2.1 for other command options for a TPM supporting field upgrade mode.
+
+NOTE 2
+
+_TPM_Hash_Start, _TPM_Hash_Data, and _TPM_Hash_End are not commands and a platform specific specification may allow these indications between _TPM_Init and TPM2_Startup().
+
+If in Failure mode the TPM shall accept TPM2_GetTestResult() and TPM2_GetCapability() even if
+TPM2_Startup() is not completed successfully or processed at all.
+A Shutdown/Startup sequence determines the way in which the TPM will operate in response to
+TPM2_Startup(). The three sequences are:
+1) TPM Reset – This is a Startup(CLEAR) preceded by either Shutdown(CLEAR) or no
+TPM2_Shutdown(). On TPM Reset, all variables go back to their default initialization state.
+NOTE 3
+
+Only those values that are specified as having a default initialization state are changed by TPM
+Reset. Persistent values that have no default initialization state are not changed by this
+command. Values such as seeds have no default initialization state and only change due to
+specific commands.
+
+2) TPM Restart – This is a Startup(CLEAR) preceded by Shutdown(STATE). This preserves much of the
+previous state of the TPM except that PCR and the controls associated with the Platform hierarchy
+are all returned to their default initialization state;
+3) TPM Resume – This is a Startup(STATE) preceded by Shutdown(STATE). This preserves the
+previous state of the TPM including the static Root of Trust for Measurement (S-RTM) PCR and the
+platform controls other than the phEnable and phEnableNV.
+If a TPM receives Startup(STATE) and that was not preceded by Shutdown(STATE), the TPM shall return
+TPM_RC_VALUE.
+If, during TPM Restart or TPM Resume, the TPM fails to restore the state saved at the last
+Shutdown(STATE), the TPM shall enter Failure Mode and return TPM_RC_FAILURE.
+On any TPM2_Startup(),
+
+
+phEnable and phEnableNV shall be SET;
+
+
+
+all transient contexts (objects, sessions, and sequences) shall be flushed from TPM memory;
+
+
+
+TPMS_TIME_INFO.time shall be reset to zero; and
+
+
+
+use of lockoutAuth shall be enabled if lockoutRecovery is zero.
+
+Additional actions are performed based on the Shutdown/Startup sequence.
+On TPM Reset
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 19
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+
+
+platformAuth and platformPolicy shall be set to the Empty Buffer,
+
+
+
+tracking data for saved session contexts shall be set to its initial value,
+
+
+
+the object context sequence number is reset to zero,
+
+
+
+a new context encryption key shall be generated,
+
+
+
+TPMS_CLOCK_INFO.restartCount shall be reset to zero,
+
+
+
+TPMS_CLOCK_INFO.resetCount shall be incremented,
+
+
+
+the PCR Update Counter shall be clear to zero,
+
+
+
+shEnable and ehEnable shall be SET, and
+
+
+
+PCR in all banks are reset to their default initial conditions as determined by the relevant platformspecific specification.
+NOTE 4
+
+PCR may be initialized any time between _TPM_Init and the end of TPM2_Startup(). PCR that
+are preserved by TPM Resume will need to be restored during TPM2_Startup().
+
+NOTE 5
+
+See "Initializing PCR" in Part 1 of this specification for a description of the default initial
+conditions for a PCR.
+
+On TPM Restart
+
+
+TPMS_CLOCK_INFO.restartCount shall be incremented,
+
+
+
+shEnable and ehEnable shall be SET,
+
+
+
+platformAuth and platformPolicy shall be set to the Empty Buffer, and
+
+
+
+PCR in all banks are reset to their default initial conditions.
+
+
+
+If a CRTM Event sequence is active, extend the PCR designated by the platform-specific
+specification.
+
+On TPM Resume
+
+
+the H-CRTM startup method is the same for this TPM2_Startup() as for the previous TPM2_Startup();
+(TPM_RC_LOCALITY)
+
+
+
+TPMS_CLOCK_INFO.restartCount shall be incremented; and
+
+
+
+PCR that are specified in a platform-specific specification to be preserved on TPM Resume are
+restored to their saved state and other PCR are set to their initial value as determined by a platformspecific specification.
+
+Other TPM state may change as required to meet the needs of the implementation.
+If the startupType is TPM_SU_STATE and the TPM requires TPM_SU_CLEAR, then the TPM shall return
+TPM_RC_VALUE.
+NOTE 6
+
+The TPM will require
+Shutdown(CLEAR).
+
+NOTE 7
+
+If startupType is neither TPM_SU_STATE nor TPM_SU_CLEAR, then the unmarshaling code returns
+TPM_RC_VALUE.
+
+Page 20
+October 31, 2013
+
+TPM_SU_CLEAR
+
+when
+
+no
+
+Published
+Copyright © TCG 2006-2013
+
+shutdown
+
+was
+
+performed
+
+or
+
+after
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+11.3.2 Command and Response
+Table 5 — TPM2_Startup Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Startup {NV}
+
+TPM_SU
+
+startupType
+
+TPM_SU_CLEAR or TPM_SU_STATE
+
+Table 6 — TPM2_Startup Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 21
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+11.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Startup_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+start up type is not compatible with previous shutdown sequence
+
+TPM_RC
+TPM2_Startup(
+Startup_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+STARTUP_TYPE
+TPM_RC
+BOOL
+
+startup;
+result;
+prevDrtmPreStartup;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation
+// Read orderly shutdown states from previous power cycle
+NvReadReserved(NV_ORDERLY, &g_prevOrderlyState);
+// HACK to extract the DRTM startup type associated with the previous shutdown
+prevDrtmPreStartup = (g_prevOrderlyState == (TPM_SU_STATE + 0x8000));
+if(prevDrtmPreStartup)
+g_prevOrderlyState = TPM_SU_STATE;
+// if the previous power cycle was shut down with no StateSave command, or
+// with StateSave command for CLEAR, this cycle can not startup up with
+// STATE
+if(
+(
+g_prevOrderlyState == SHUTDOWN_NONE
+|| g_prevOrderlyState == TPM_SU_CLEAR
+)
+&& in->startupType == TPM_SU_STATE
+)
+return TPM_RC_VALUE + RC_Startup_startupType;
+// Internal Date Update
+// Translate the TPM2_ShutDown and TPM2_Startup sequence into the startup
+// types.
+if(in->startupType == TPM_SU_CLEAR && g_prevOrderlyState == TPM_SU_STATE)
+{
+startup = SU_RESTART;
+// Read state reset data
+NvReadReserved(NV_STATE_RESET, &gr);
+}
+else if(in->startupType == TPM_SU_STATE && g_prevOrderlyState == TPM_SU_STATE)
+{
+// For a resume, the H-CRTM startup method must be the same
+if(g_DrtmPreStartup != prevDrtmPreStartup)
+return TPM_RC_LOCALITY;
+
+Page 22
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+
+Part 3: Commands
+
+// Read state clear and state reset data
+NvReadReserved(NV_STATE_CLEAR, &gc);
+NvReadReserved(NV_STATE_RESET, &gr);
+startup = SU_RESUME;
+}
+else
+{
+startup = SU_RESET;
+}
+// Read persistent data from NV
+NvReadPersistent();
+// Crypto Startup
+CryptUtilStartup(startup);
+// Start up subsystems
+// Start counters and timers
+TimeStartup(startup);
+// Start dictionary attack subsystem
+DAStartup(startup);
+// Enable hierarchies
+HierarchyStartup(startup);
+// Restore/Initialize PCR
+PCRStartup(startup);
+// Restore/Initialize command audit information
+CommandAuditStartup(startup);
+// Object context variables
+if(startup == SU_RESET)
+{
+// Reset object context ID to 0
+gr.objectContextID = 0;
+// Reset clearCount to 0
+gr.clearCount= 0;
+}
+// Initialize object table
+ObjectStartup();
+// Initialize session table
+SessionStartup(startup);
+// Initialize index/evict data.
+// in NV index
+NvEntityStartup(startup);
+
+This function clear read/write locks
+
+// Initialize the orderly shut down flag for this cycle to SHUTDOWN_NONE.
+gp.orderlyState = SHUTDOWN_NONE;
+NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
+// Update TPM internal states if command succeeded.
+// Record a TPM2_Startup command has been received.
+TPMRegisterStartup();
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 23
+October 31, 2013
+
+ Part 3: Commands
+
+11.4
+
+Trusted Platform Module Library
+
+TPM2_Shutdown
+
+11.4.1 General Description
+This command is used to prepare the TPM for a power cycle. The shutdownType parameter indicates
+how the subsequent TPM2_Startup() will be processed.
+For a shutdownType of any type, the volatile portion of Clock is saved to NV memory and the orderly
+shutdown indication is SET. NV with the TPMA_NV_ORDERY attribute will be updated.
+For a shutdownType of TPM_SU_STATE, the following additional items are saved:
+
+
+tracking information for saved session contexts;
+
+
+
+the session context counter;
+
+
+
+PCR that are designated as being preserved by TPM2_Shutdown(TPM_SU_STATE);
+
+
+
+the PCR Update Counter;
+
+
+
+flags associated with supporting the TPMA_NV_WRITESTCLEAR and TPMA_NV_READSTCLEAR
+attributes; and
+
+
+
+the command audit digest and count.
+
+The following items shall not be saved and will not be in TPM memory after the next TPM2_Startup:
+
+
+TPM-memory-resident session contexts;
+
+
+
+TPM-memory-resident transient objects; or
+
+
+
+TPM-memory-resident hash contexts created by TPM2_HashSequenceStart().
+
+Some values may be either derived from other values or saved to NV memory.
+This command saves TPM state but does not change the state other than the internal indication that the
+context has been saved. The TPM shall continue to accept commands. If a subsequent command
+changes TPM state saved by this command, then the effect of this command is nullified. The TPM MAY
+nullify this command for any subsequent command rather than check whether the command changed
+state saved by this command. If this command is nullified. and if no TPM2_Shutdown() occurs before the
+next TPM2_Startup(), then the next TPM2_Startup() shall be TPM2_Startup(CLEAR).
+
+Page 24
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+11.4.2 Command and Response
+Table 7 — TPM2_Shutdown Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Shutdown {NV}
+
+TPM_SU
+
+shutdownType
+
+TPM_SU_CLEAR or TPM_SU_STATE
+
+Table 8 — TPM2_Shutdown Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 25
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+11.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Shutdown_fp.h"
+Error Returns
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+if PCR bank has been re-configured, a CLEAR StateSave() is
+required
+
+TPM_RC
+TPM2_Shutdown(
+Shutdown_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// If PCR bank has been reconfigured, a CLEAR state save is required
+if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE)
+return TPM_RC_TYPE + RC_Shutdown_shutdownType;
+// Internal Data Update
+// PCR private date state save
+PCRStateSave(in->shutdownType);
+// Get DRBG state
+CryptDrbgGetPutState(GET_STATE);
+// Save all orderly data
+NvWriteReserved(NV_ORDERLY_DATA, &go);
+// Save RAM backed NV index data
+NvStateSave();
+if(in->shutdownType == TPM_SU_STATE)
+{
+// Save STATE_RESET and STATE_CLEAR data
+NvWriteReserved(NV_STATE_CLEAR, &gc);
+NvWriteReserved(NV_STATE_RESET, &gr);
+}
+else if(in->shutdownType == TPM_SU_CLEAR)
+{
+// Save STATE_RESET data
+NvWriteReserved(NV_STATE_RESET, &gr);
+}
+// Write orderly shut down state
+if(in->shutdownType == TPM_SU_CLEAR)
+gp.orderlyState = TPM_SU_CLEAR;
+else if(in->shutdownType == TPM_SU_STATE)
+gp.orderlyState = TPM_SU_STATE;
+else
+
+Page 26
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+55
+56
+57
+58
+59
+
+Part 3: Commands
+
+pAssert(FALSE);
+NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 27
+October 31, 2013
+
+ Part 3: Commands
+
+12
+12.1
+
+Trusted Platform Module Library
+
+Testing
+Introduction
+
+Compliance to standards for hardware security modules may require that the TPM test its functions
+before the results that depend on those functions may be returned. The TPM may perform operations
+using testable functions before those functions have been tested as long as the TPM returns no value
+that depends on the correctness of the testable function.
+EXAMPLE
+
+TPM2_PCR_Event() may be executed before the hash algorithms have been tested. However, until
+the hash algorithms have been tested, the contents of a PCR may not be used in any command if
+that command may result in a value being returned to the TPM user. This means tha t
+TPM2_PCR_Read() or TPM2_PolicyPCR() could not complete until the hashes have been checked
+but other TPM2_PCR_Event() commands may be executed even though the operation uses previous
+PCR values.
+
+If a command is received that requires return of a value that depends on untested functions, the TPM
+shall test the required functions before completing the command.
+Once the TPM has received TPM2_SelfTest() and before completion of all tests, the TPM is required to
+return TPM_RC_TESTING for any command that uses a function that requires a test.
+If a self-test fails at any time, the TPM will enter Failure mode. While in Failure mode, the TPM will return
+TPM_RC_FAILURE for any command other than TPM2_GetTestResult() and TPM2_GetCapability(). The
+TPM will remain in Failure mode until the next _TPM_Init.
+
+Page 28
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+12.2
+
+Part 3: Commands
+
+TPM2_SelfTest
+
+12.2.1 General Description
+This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, the TPM will test
+all functions. If fullTest = NO, the TPM will only test those functions that have not previously been tested.
+If any tests are required, the TPM shall either
+a) return TPM_RC_TESTING and begin self-test of the required functions, or
+NOTE 1
+
+If fullTest is NO, and all functions have been tested, the TPM shall return TPM_RC_SUCCESS.
+
+b) perform the tests and return the test result when complete.
+If the TPM uses option a), the TPM shall return TPM_RC_TESTING for any command that requires use
+of a testable function, even if the functions required for completion of the command have already been
+tested.
+NOTE 2
+
+This command may cause the TPM to continue processing after it has returned the response. So
+that software can be notified of the completion of the testing, the interface may include controls that
+would allow the TPM to generate an interrupt when the “background” processing is complete. This
+would be in addition to the interrupt may be available for signaling normal command completion. It is
+not necessary that there be two interrupts, but the interface should provide a way to indicate the
+nature of the interrupt (normal command or deferred command).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 29
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+12.2.2 Command and Response
+Table 9 — TPM2_SelfTest Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SelfTest {NV}
+
+TPMI_YES_NO
+
+fullTest
+
+YES if full test to be performed
+NO if only test of untested functions required
+
+Table 10 — TPM2_SelfTest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 30
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+12.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "SelfTest_fp.h"
+Error Returns
+TPM_RC_TESTING
+
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+Meaning
+self test in process
+
+TPM_RC
+TPM2_SelfTest(
+SelfTest_In
+)
+{
+// Command Output
+
+*in
+
+// IN: input parameter list
+
+// Call self test function in crypt module
+return CryptSelfTest(in->fullTest);
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 31
+October 31, 2013
+
+ Part 3: Commands
+
+12.3
+
+Trusted Platform Module Library
+
+TPM2_IncrementalSelfTest
+
+12.3.1 General Description
+This command causes the TPM to perform a test of the selected algorithms.
+NOTE 1
+
+The toTest list indicates the algorithms that software would like the TPM to test in anticipation of
+future use. This allows tests to be done so that a future commands will not be delayed due to
+testing.
+
+If toTest contains an algorithm that has already been tested, it will not be tested again.
+NOTE 2
+
+The only way to force retesting of an algorithm is with TPM2_SelfTest( fullTest = YES).
+
+The TPM will return in toDoList a list of algorithms that are yet to be tested. This list is not the list of
+algorithms that are scheduled to be tested but the algorithms/functions that have not been tested. Only
+the algorithms on the toTest list are scheduled to be tested by this command.
+Making toTest an empty list allows the determination of the algorithms that remain untested without
+triggering any testing.
+If toTest is not an empty list, the TPM shall return TPM_RC_SUCCESS for this command and then return
+TPM_RC_TESTING for any subsequent command (including TPM2_IncrementalSelfTest()) until the
+requested testing is complete.
+NOTE 3
+
+If toDoList is empty, then no additional tests are required and TPM_RC_TESTING will not be
+returned in subsequent commands and no additional delay will occur in a command due to testing.
+
+NOTE 4
+
+If none of the algorithms listed in toTest is in the toDoList, then no tests will be performed.
+
+If all the parameters in this command are valid, the TPM returns TPM_RC_SUCCESS and the toDoList
+(which may be empty).
+NOTE 5
+
+An implementation may perform all requested tests before returning TPM_RC_SUCCESS, or it may
+return TPM_RC_SUCCESS for this command and then return TPM_RC_TESTING for all
+subsequence commands (including TPM2_IncrementatSelfTest()) until the requested tests are
+complete.
+
+Page 32
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+12.3.2 Command and Response
+Table 11 — TPM2_IncrementalSelfTest Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_IncrementalSelfTest {NV}
+
+TPML_ALG
+
+toTest
+
+list of algorithms that should be tested
+
+Table 12 — TPM2_IncrementalSelfTest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPML_ALG
+
+toDoList
+
+Family “2.0”
+Level 00 Revision 00.99
+
+list of algorithms that need testing
+
+Published
+Copyright © TCG 2006-2013
+
+Page 33
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+12.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+#include "InternalRoutines.h"
+#include "IncrementalSelfTest_fp.h"
+
+TPM_RC
+TPM2_IncrementalSelfTest(
+IncrementalSelfTest_In
+IncrementalSelfTest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Call incremental self test function in crypt module
+return CryptIncrementalSelfTest(&in->toTest, &out->toDoList);
+}
+
+Page 34
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+12.4
+
+Part 3: Commands
+
+TPM2_GetTestResult
+
+12.4.1 General Description
+This command returns manufacturer-specific information regarding the results of a self-test and an
+indication of the test status.
+If TPM2_SelfTest() has not been executed and a testable function has not been tested, testResult will be
+TPM_RC_NEEDS_TEST. If TPM2_SelfTest() has been received and the tests are not complete,
+testResult will be TPM_RC_TESTING. If testing of all functions is complete without functional failures,
+testResult will be TPM_RC_SUCCESS. If any test failed, testResult will be TPM_RC_FAILURE. If the
+TPM is in Failure mode because of an invalid startupType in TPM2_Startup(), testResult will be
+TPM_RC_INITIALIZE.
+This command will operate when the TPM is in Failure mode so that software can determine the test
+status of the TPM and so that diagnostic information can be obtained for use in failure analysis. If the
+TPM is in Failure mode, then tag is required to be TPM_ST_NO_SESSIONS or the TPM shall return
+TPM_RC_FAILURE.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 35
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+12.4.2 Command and Response
+Table 13 — TPM2_GetTestResult Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetTestResult
+
+Table 14 — TPM2_GetTestResult Response
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_BUFFER
+
+outData
+
+TPM_RC
+
+testResult
+
+Page 36
+October 31, 2013
+
+test result data
+contains manufacturer-specific information
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+12.4.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+#include "InternalRoutines.h"
+#include "GetTestResult_fp.h"
+
+TPM_RC
+TPM2_GetTestResult(
+GetTestResult_Out
+)
+{
+// Command Output
+
+*out
+
+// OUT: output parameter list
+
+// Call incremental self test function in crypt module
+out->testResult = CryptGetTestResult(&out->outData);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 37
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Session Commands
+
+13
+13.1
+
+TPM2_StartAuthSession
+
+13.1.1 General Description
+This command is used to start an authorization session using alternative methods of establishing the
+session key (sessionKey). The session key is then used to derive values used for authorization and for
+encrypting parameters.
+This command allows injection of a secret into the TPM using either asymmetric or symmetric encryption.
+The type of tpmKey determines how the value in encryptedSalt is encrypted. The decrypted secret value
+is used to compute the sessionKey.
+NOTE 1
+
+If tpmKey Is TPM_RH_NULL, then encryptedSalt is required to be an Empty Buffer.
+
+The label value of “SECRET” (see “Terms and Definitions” in Part 1 of this specification) is used in the
+recovery of the secret value.
+The TPM generates the sessionKey from the recovered secret value.
+No authorization is required for tpmKey or bind.
+NOTE 2
+
+The justification for using tpmKey without providing authorization is that the result o f using the key is
+not available to the caller, except indirectly through the sessionKey. This does not represent a point
+of attack on the value of the key. If the caller attempts to use the session without knowing the
+sessionKey value, it is an authorization failure that will trigger the dictionary attack logic.
+
+The entity referenced with the bind parameter contributes an authorization value to the sessionKey
+generation process.
+If both tpmKey and bind are TPM_ALG_NULL, then sessionKey is set to the Empty Buffer. If tpmKey is
+not TPM_ALG_NULL, then encryptedSalt is used in the computation of sessionKey. If bind is not
+TPM_ALG_NULL, the authValue of bind is used in the sessionKey computation.
+If symmetric specifies a block cipher, then TPM_ALG_CFB is the only allowed value for the mode field in
+the symmetric parameter (TPM_RC_MODE).
+This command starts an authorization session and returns the session handle along with an initial
+nonceTPM in the response.
+If the TPM does not have
+TPM_RC_SESSION_HANDLES.
+
+a
+
+free
+
+slot
+
+for
+
+an
+
+authorization
+
+session,
+
+it
+
+shall
+
+return
+
+If the TPM implements a “gap” scheme for assigning contextID values, then the TPM shall return
+TPM_RC_CONTEXT_GAP if creating the session would prevent recycling of old saved contexts (See
+“Context Management” in Part 1).
+If tpmKey is not TPM_ALG_NULL then encryptedSalt shall be a TPM2B_ENCRYPTED_SECRET of the
+proper type for tpmKey. The TPM shall return TPM_RC_VALUE if:
+a) tpmKey references an RSA key and
+1) encryptedSalt does not contain a value that is the size of the public modulus of tpmKey,
+2) encryptedSalt has a value that is greater than the public modulus of tpmKey,
+3) encryptedSalt is not a properly encode OAEP value, or
+4) the decrypted salt value is larger than the size of the digest produced by the nameAlg of tpmKey;
+or
+
+Page 38
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+b) tpmKey references an ECC key and encryptedSalt
+1) does not contain a TPMS_ECC_POINT or
+2) is not a point on the curve of tpmKey;
+NOTE 3
+
+When ECC is used, the point multiply process produces a value (Z) that is used in a KDF to
+produce the final secret value. The size of the secret value is an input parameter to the KDF
+and the result will be set to be the size of the digest produced by the nameAlg of tpmKey.
+
+c) tpmKey references a symmetric block cipher or a keyedHash object and encryptedSalt contains a
+value that is larger than the size of the digest produced by the nameAlg of tpmKey.
+For all session types, this command will cause initialization of the sessionKey and may establish binding
+between the session and an object (the bind object). If sessionType is TPM_SE_POLICY or
+TPM_SE_TRIAL, the additional session initialization is:
+
+
+set policySession→policyDigest to a Zero Digest (the digest size for policySession→policyDigest is
+the size of the digest produced by authHash);
+
+
+
+authorization may be given at any locality;
+
+
+
+authorization may apply to any command code;
+
+
+
+authorization may apply to any command parameters or handles;
+
+
+
+the authorization has no time limit;
+
+
+
+an authValue is not needed when the authorization is used;
+
+
+
+the session is not bound;
+
+
+
+the session is not an audit session; and
+
+
+
+the time at which the policy session was created is recorded.
+
+Additionally, if sessionType is TPM_SE_TRIAL, the session will not be usable for authorization but can be
+used to compute the authPolicy for an object.
+NOTE 4
+
+Although this command changes the session allocation information in the TPM, it does not invalidate
+a saved context. That is, TPM2_Shutdown() is not required after this comm and in order to reestablish the orderly state of the TPM. This is because the created context will occupy an available
+slot in the TPM and sessions in the TPM do not survive any TPM2_Startup(). However, if a created
+session is context saved, the orderly state does change.
+
+The TPM shall return TPM_RC_SIZE if nonceCaller is less than 16 octets or is greater than the size of
+the digest produced by authHash.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 39
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+13.1.2 Command and Response
+Table 15 — TPM2_StartAuthSession Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_StartAuthSession
+
+TPMI_DH_OBJECT+
+
+tpmKey
+
+handle of a loaded decrypt key used to encrypt salt
+may be TPM_RH_NULL
+Auth Index: None
+
+TPMI_DH_ENTITY+
+
+bind
+
+entity providing the authValue
+may be TPM_RH_NULL
+Auth Index: None
+
+TPM2B_NONCE
+
+nonceCaller
+
+Description
+
+initial nonceCaller, sets nonce size for the session
+shall be at least 16 octets
+
+TPM2B_ENCRYPTED_SECRET
+
+encryptedSalt
+
+value encrypted according to the type of tpmKey
+If tpmKey is TPM_RH_NULL, this shall be the Empty
+Buffer.
+
+TPM_SE
+
+sessionType
+
+indicates the type of the session; simple HMAC or policy
+(including a trial policy)
+
+TPMT_SYM_DEF+
+
+symmetric
+
+the algorithm and key size for parameter encryption
+may select TPM_ALG_NULL
+
+TPMI_ALG_HASH
+
+authHash
+
+hash algorithm to use for the session
+Shall be a hash algorithm supported by the TPM and
+not TPM_ALG_NULL
+
+Table 16 — TPM2_StartAuthSession Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_SH_AUTH_SESSION
+
+sessionHandle
+
+handle for the newly created session
+
+TPM2B_NONCE
+
+nonceTPM
+
+the initial nonce from the TPM, used in the computation
+of the sessionKey
+
+Page 40
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+13.1.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "StartAuthSession_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+tpmKey does not reference a decrypt key
+
+TPM_RC_CONTEXT_GAP
+
+the difference between the most recently created active context and
+the oldest active context is at the limits of the TPM
+
+TPM_RC_HANDLE
+
+input decrypt key handle only has public portion loaded
+
+TPM_RC_MODE
+
+symmetric specifies a block cipher but the mode is not
+TPM_ALG_CFB.
+
+TPM_RC_SESSION_HANDLES
+
+no session handle is available
+
+TPM_RC_SESSION_MEMORY
+
+no more slots for loading a session
+
+TPM_RC_SIZE
+
+nonce less than 16 octets or greater than the size of the digest
+produced by authHash
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+
+Meaning
+
+secret size does not match decrypt key type; or the recovered secret
+is larget than the digest size of the nameAlg of tpmKey; or, for an
+RSA decrypt key, if encryptedSecret is greater than the public
+exponent of tpmKey.
+
+TPM_RC
+TPM2_StartAuthSession(
+StartAuthSession_In
+StartAuthSession_Out
+
+*in,
+*out
+
+// IN: input parameter buffer
+// OUT: output parameter buffer
+
+TPM_RC
+OBJECT
+SESSION
+TPM2B_DATA
+
+result = TPM_RC_SUCCESS;
+*tpmKey;
+// TPM key for decrypt salt
+*session;
+// session internal data
+salt;
+
+)
+{
+
+// Input Validation
+// Check input nonce size. IT should be at least 16 bytes but not larger
+// than the digest size of session hash.
+if(
+in->nonceCaller.t.size < 16
+|| in->nonceCaller.t.size > CryptGetHashDigestSize(in->authHash))
+return TPM_RC_SIZE + RC_StartAuthSession_nonceCaller;
+// If an decrypt key is passed in, check its validation
+if(in->tpmKey != TPM_RH_NULL)
+{
+// secret size cannot be 0
+if(in->encryptedSalt.t.size == 0)
+return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
+// Get pointer to loaded decrypt key
+tpmKey = ObjectGet(in->tpmKey);
+// Decrypting salt requires accessing the private portion of a key.
+// Therefore, tmpKey can not be a key with only public portion loaded
+if(tpmKey->attributes.publicOnly)
+return TPM_RC_HANDLE + RC_StartAuthSession_tpmKey;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 41
+October 31, 2013
+
+ Part 3: Commands
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+
+Trusted Platform Module Library
+
+// HMAC session input handle check.
+// tpmKey should be a decryption key
+if(tpmKey->publicArea.objectAttributes.decrypt != SET)
+return TPM_RC_ATTRIBUTES + RC_StartAuthSession_tpmKey;
+// Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors
+// may be returned at this point
+result = CryptSecretDecrypt(in->tpmKey, &in->nonceCaller, "SECRET",
+&in->encryptedSalt, &salt);
+if(result != TPM_RC_SUCCESS)
+return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
+}
+else
+{
+// secret size must be 0
+if(in->encryptedSalt.t.size != 0)
+return TPM_RC_VALUE + RC_StartAuthSession_encryptedSalt;
+salt.t.size = 0;
+}
+// If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR)
+// then the mode must be CFB.
+if(
+in->symmetric.algorithm != TPM_ALG_NULL
+&& in->symmetric.algorithm != TPM_ALG_XOR
+&& in->symmetric.mode.sym != TPM_ALG_CFB)
+return TPM_RC_MODE + RC_StartAuthSession_symmetric;
+// Internal Data Update
+// Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES
+// or TPM_RC_SESSION_MEMORY errors may be returned returned at this point.
+//
+// The detailed actions for creating the session context are not shown here
+// as the details are implementation dependent
+// SessionCreate sets the output handle
+result = SessionCreate(in->sessionType, in->authHash,
+&in->nonceCaller, &in->symmetric,
+in->bind, &salt, &out->sessionHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Command Output
+// Get session pointer
+session = SessionGet(out->sessionHandle);
+// Copy nonceTPM
+out->nonceTPM = session->nonceTPM;
+return TPM_RC_SUCCESS;
+}
+
+Page 42
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+13.2
+
+Part 3: Commands
+
+TPM2_PolicyRestart
+
+13.2.1 General Description
+This command allows a policy authorization session to be returned to its initial state. This command is
+used after the TPM returns TPM_RC_PCR_CHANGED. That response code indicates that a policy will
+fail because the PCR have changed after TPM2_PolicyPCR() was executed. Restarting the session
+allows the authorizations to be replayed because the session restarts with the same nonceTPM. If the
+PCR are valid for the policy, the policy may then succeed.
+This command does not reset the policy ID or the policy start time.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 43
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+13.2.2 Command and Response
+Table 17 — TPM2_PolicyRestart Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyRestart
+
+TPMI_SH_POLICY
+
+sessionHandle
+
+the handle for the policy session
+
+Table 18 — TPM2_PolicyRestart Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 44
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+13.2.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
+#include "InternalRoutines.h"
+#include "PolicyRestart_fp.h"
+
+TPM_RC
+TPM2_PolicyRestart(
+PolicyRestart_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+BOOL
+
+*session;
+wasTrialSession;
+
+)
+{
+
+// Internal Data Update
+session = SessionGet(in->sessionHandle);
+wasTrialSession = session->attributes.isTrialPolicy == SET;
+// Initialize policy session
+SessionResetPolicyData(session);
+session->attributes.isTrialPolicy = wasTrialSession;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 45
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+Object Commands
+
+14
+14.1
+
+TPM2_Create
+
+14.1.1 General Description
+This command is used to create an object that can be loaded into a TPM using TPM2_Load(). If the
+command completes successfully, the TPM will create the new object and return the object’s creation
+data (creationData), its public area (outPublic), and its encrypted sensitive area (outPrivate). Preservation
+of the returned data is the responsibility of the caller. The object will need to be loaded (TPM2_Load())
+before it may be used.
+TPM2B_PUBLIC template (inPublic) contains all of the fields necessary to define the properties of the
+new object. The setting for these fields is defined in “Public Area Template” in Part 1 and
+“TPMA_OBJECT” in Part 2.
+The parentHandle parameter shall reference a loaded decryption key that has both the public and
+sensitive area loaded.
+When defining the object, the caller provides a template structure for the object in a TPM2B_PUBLIC
+structure (inPublic), an initial value for the object’s authValue (inSensitive.authValue), and, if the object is
+a symmetric object, an optional initial data value (inSensitive.data). The TPM shall validate the
+consistency of inPublic.attributes according to the Creation rules in “TPMA_OBJECT” in Part 2.
+The sensitive parameter may be encrypted using parameter encryption.
+The methods in this clause are used by both TPM2_Create() and TPM2_CreatePrimary(). When a value
+is indicated as being TPM-generated, the value is filled in by bits from the RNG if the command is
+TPM2_Create() and with values from KDFa() if the command is TPM2_CreatePrimary(). The parameters
+of each creation value are specified in Part 1.
+The sensitiveDataOrigin attribute of inPublic shall be SET if inSensitive.data is an Empty Buffer and
+CLEAR if inSensitive.data is not an Empty Buffer or the TPM shall return TPM_RC_ATTRIBUTES.
+The TPM will create new data for the sensitive area and compute a TPMT_PUBLIC.unique from the
+sensitive area based on the object type:
+a) For a symmetric key:
+1) If inSensitive.data is the Empty Buffer, a TPM-generated key value is placed in the new object’s
+TPMT_SENSITIVE.sensitive.sym. The size of the key will be determined by
+inPublic.publicArea.parameters.
+2) If inSensitive.data is not the Empty Buffer, the TPM will validate that the size of inSensitive.data is
+no larger than the key size indicated in the inPublic template (TPM_RC_SIZE) and copy the
+inSensitive.data to TPMT_SENSITIVE.sensitive.sym of the new object.
+3) A TPM-generated obfuscation value is placed in TPMT_SENSITIVE.sensitive.seedValue. The
+size of the obfuscation value is the size of the digest produced by the nameAlg in inPublic. This
+value prevents the public unique value from leaking information about the sensitive area.
+4) The TPMT_PUBLIC.unique.sym.buffer value for the new object is then generated, as shown in
+equation (1) below, by hashing the key and obfuscation values in the TPMT_SENSITIVE with the
+nameAlg of the object.
+
+unique ≔ HnameAlg(sensitive.seedValue.buffer || sensitive.any.buffer)
+
+(1)
+
+b) If the Object is an asymmetric key:
+1) If sensitive.data is not the Empty Buffer, then the TPM shall return TPM_RC_VALUE.
+
+Page 46
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+2) A TPM-generated private key value is created with the size determined by the parameters of
+inPublic.publicArea.parameters.
+3) If the key is a Storage Key, a TPM-generated TPMT_SENSITIVE.symKey value is created;
+otherwise, TPMT_SENSITIVE.symKey.size is set to zero.
+4) The public unique value is computed from the private key according to the methods of the key
+type.
+5) If the key is an ECC key and the scheme required by the curveID is not the same as scheme in
+the public area of the template, then the TPM shall return TPM_RC_SCHEME.
+6) If the key is an ECC key and the KDF required by the curveID is not the same as kdf in the pubic
+area of the template, then the TPM shall return TPM_RC_KDF.
+NOTE 1
+
+There is currently no command in which the caller may specify the KDF to be used with an
+ECC decryption key. Since there is no use for this capability, the reference implementation
+requires that the kdf in the template be set to TPM_ALG_NULL or TPM_RC_KDF is
+returned.
+
+c) If the Object is a keyedHash object:
+1) If inSensitive.data is an Empty Buffer, and neither sign nor decrypt is SET in inPublic.attributes,
+the TPM shall return TPM_RC_ATTRIBUTES. This would be a data object with no data.
+2) If inSensitive.data is not an Empty Buffer, the TPM will copy the inSensitive.data to
+TPMT_SENSITIVE.sensitive of the new object.
+NOTE 2
+
+The size of inSensitive.data is limited to be no larger
+TPMT_SENSITIVE.sensitive.bits.data by MAX_SYM_DATA.
+
+than
+
+the
+
+largest
+
+value
+
+of
+
+3) If inSensitive.data is an Empty Buffer, a TPM-generated key value that is the size of the digest
+produced by the nameAlg in inPublic is placed in TPMT_SENSITIVE.sensitive.any.buffer.
+4) A TPM-generated obfuscation value that is the size of the digest produced by the nameAlg of
+inPublic is placed in TPMT_SENSITIVE.symKey.buffer.
+5) The TPMT_PUBLIC.unique.sym.buffer value for the new object is then generated, as shown in
+equation (1) above, by hashing the key and obfuscation values in the TPMT_SENSITIVE with the
+nameAlg of the object.
+For TPM2_Load(), the TPM will apply normal symmetric protections to the created TPMT_SENSITIVE to
+create outPublic.
+NOTE 3
+
+The encryption key is derived from the symmetric seed in the sensitive area of the parent.
+
+In addition to outPublic and outPrivate, the TPM will build a TPMS_CREATION_DATA structure for the
+object. TPMS_CREATION_DATA.outsideInfo is set to outsideInfo. This structure is returned in
+creationData. Additionally, the digest of this structure is returned in creationHash, and, finally, a
+TPMT_TK_CREATION is created so that the association between the creation data and the object may
+be validated by TPM2_CertifyCreation().
+If the object being created is a Storage Key and inPublic.objectAttributes.fixedParent is SET, then the
+algorithms of inPublic are required to match those of the parent. The algorithms that must match are
+inPublic.type, inPublic.nameAlg, and inPublic.parameters. If inPublic.type does not match, the TPM shall
+return TPM_RC_TYPE. If inPublic.nameAlg does not match, the TPM shall return TPM_RC_HASH. If
+inPublic.parameters does not match, the TPM shall return TPM_RC_ASSYMETRIC. The TPM shall not
+differentiate between mismatches of the components of inPublic.parameters.
+EXAMPLE
+
+If the inPublic.parameters.ecc.symmetric.algorithm does not match the parent, the TPM shall return
+TPM_RC_ ASYMMETRIC rather than TPM_RC_SYMMETRIC.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 47
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.1.2 Command and Response
+Table 19 — TPM2_Create Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Create
+
+TPMI_DH_OBJECT
+
+@parentHandle
+
+handle of parent for new object
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_SENSITIVE_CREATE
+
+inSensitive
+
+the sensitive data
+
+TPM2B_PUBLIC
+
+inPublic
+
+the public template
+
+TPM2B_DATA
+
+outsideInfo
+
+data that will be included in the creation data for this
+object to provide permanent, verifiable linkage between
+this object and some object owner data
+
+TPML_PCR_SELECTION
+
+creationPCR
+
+PCR that will be used in creation data
+
+Table 20 — TPM2_Create Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outPrivate
+
+the private portion of the object
+
+TPM2B_PUBLIC
+
+outPublic
+
+the public portion of the created object
+
+TPM2B_CREATION_DATA
+
+creationData
+
+contains a TPMS_CREATION_DATA
+
+TPM2B_DIGEST
+
+creationHash
+
+digest of creationData using nameAlg of outPublic
+
+TPMT_TK_CREATION
+
+creationTicket
+
+ticket used by TPM2_CertifyCreation() to validate that
+the creation data was produced by the TPM
+
+Page 48
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.1.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Object_spt_fp.h"
+#include "Create_fp.h"
+Error Returns
+TPM_RC_ASYMMETRIC
+
+non-duplicable storage key and its parent have different public
+params
+
+TPM_RC_ATTRIBUTES
+
+sensitiveDataOrigin is CLEAR when 'sensitive. data' is an Empty
+Buffer, or is SET when 'sensitive. data' is not empty; fixedTPM,
+fixedParent, or encryptedDuplication attributes are inconsistent
+between themselves or with those of the parent object; inconsistent
+restricted, decrypt and sign attributes; attempt to inject sensitive data
+for an asymmetric key; attempt to create a symmetric cipher key that
+is not a decryption key
+
+TPM_RC_HASH
+
+non-duplicable storage key and its parent have different name
+algorithm
+
+TPM_RC_KDF
+
+incorrect KDF specified for decrypting keyed hash object
+
+TPM_RC_KEY
+
+invalid key size values in an asymmetric key public area
+
+TPM_RC_KEY_SIZE
+
+key size in public area for symmetric key differs from the size in the
+sensitive creation area; may also be returned if the TPM does not
+allow the key size to be used for a Storage Key
+
+TPM_RC_RANGE
+
+FOr() an RSA key, the exponent value is not supported.
+
+TPM_RC_SCHEME
+
+inconsistent attributes decrypt, sign, restricted and key's scheme ID;
+or hash algorithm is inconsistent with the scheme ID for keyed hash
+object
+
+TPM_RC_SIZE
+
+size of public auth policy or sensitive auth value does not match
+digest size of the name algorithm sensitive data size for the keyed
+hash object is larger than is allowed for the scheme
+
+TPM_RC_SYMMETRIC
+
+a storage key with no symmetric algorithm specified; or non-storage
+key with symmetric algorithm different from TPM_ALG_NULL
+
+TPM_RC_TYPE
+
+unknown object type; non-duplicable storage key and its parent have
+different types; parentHandle does not reference a restricted
+decryption key in the storage hierarchy with both public and sensitive
+portion loaded
+
+TPM_RC_VALUE
+
+exponent is not prime or could not find a prime using the provided
+parameters for an RSA key; unsupported name algorithm for an ECC
+key
+
+TPM_RC_OBJECT_MEMORY
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+Meaning
+
+there is no free slot for the object. This implementation does not
+return this error.
+
+TPM_RC
+TPM2_Create(
+Create_In
+Create_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMT_SENSITIVE
+TPM2B_NAME
+
+Family “2.0”
+Level 00 Revision 00.99
+
+result = TPM_RC_SUCCESS;
+sensitive;
+name;
+
+Published
+Copyright © TCG 2006-2013
+
+Page 49
+October 31, 2013
+
+ Part 3: Commands
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
+Trusted Platform Module Library
+
+// Input Validation
+OBJECT
+
+*parentObject;
+
+parentObject = ObjectGet(in->parentHandle);
+// Does parent have the proper attributes?
+if(!AreAttributesForParent(parentObject))
+return TPM_RC_TYPE + RC_Create_parentHandle;
+// The sensitiveDataOrigin attribute must be consistent with the setting of
+// the size of the data object in inSensitive.
+if(
+(in->inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin == SET)
+!= (in->inSensitive.t.sensitive.data.t.size == 0))
+// Mismatch between the object attributes and the parameter.
+return TPM_RC_ATTRIBUTES + RC_Create_inSensitive;
+// Check attributes in input public area. TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES,
+// TPM_RC_HASH, TPM_RC_KDF, TPM_RC_SCHEME, TPM_RC_SIZE, TPM_RC_SYMMETRIC,
+// or TPM_RC_TYPE error may be returned at this point.
+result = PublicAttributesValidation(FALSE, in->parentHandle,
+&in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Create_inPublic);
+// Validate the sensitive area values
+if( MemoryRemoveTrailingZeros(&in->inSensitive.t.sensitive.userAuth)
+> CryptGetHashDigestSize(in->inPublic.t.publicArea.nameAlg))
+return TPM_RC_SIZE + RC_Create_inSensitive;
+// Command Output
+// Create object crypto data
+result = CryptCreateObject(in->parentHandle, &in->inPublic.t.publicArea,
+&in->inSensitive.t.sensitive, &sensitive);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Fill in creation data
+FillInCreationData(in->parentHandle, in->inPublic.t.publicArea.nameAlg,
+&in->creationPCR, &in->outsideInfo,
+&out->creationData, &out->creationHash);
+// Copy public area from input to output
+out->outPublic.t.publicArea = in->inPublic.t.publicArea;
+// Compute name from public area
+ObjectComputeName(&(out->outPublic.t.publicArea), &name);
+// Compute creation ticket
+TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &name,
+&out->creationHash, &out->creationTicket);
+// Prepare output private data from sensitive
+SensitiveToPrivate(&sensitive, &name, in->parentHandle,
+out->outPublic.t.publicArea.nameAlg,
+&out->outPrivate);
+return TPM_RC_SUCCESS;
+}
+
+Page 50
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.2
+
+Part 3: Commands
+
+TPM2_Load
+
+14.2.1 General Description
+This command is used to load objects into the TPM. This command is used when both a TPM2B_PUBLIC
+and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be loaded, the
+TPM2_LoadExternal command is used.
+NOTE 1
+
+Loading an object is not the same as restoring a saved object context.
+
+The object’s TPMA_OBJECT attributes will be checked according to the rules defined in
+“TPMA_OBJECT” in Part 2 of this specification.
+Objects loaded using this command will have a Name. The Name is the concatenation of nameAlg and
+the digest of the public area using the nameAlg.
+NOTE 2
+
+nameAlg is a parameter in the public area of the inPublic structure.
+
+If inPrivate.size is zero, the load will fail.
+After inPrivate.buffer is decrypted using the symmetric key of the parent, the integrity value shall be
+checked before the sensitive area is used, or unmarshaled.
+NOTE 3
+
+Checking the integrity before the data is used prevents attacks o n the sensitive area by fuzzing the
+data and looking at the differences in the response codes.
+
+The command returns a handle for the loaded object and the Name that the TPM computed for
+inPublic.public (that is, the digest of the TPMT_PUBLIC structure in inPublic).
+NOTE 4
+
+The TPM-computed Name is provided as a convenience to the caller for those cases where the
+caller does not implement the hash algorithms specified in the nameAlg of the object.
+
+NOTE 5
+
+The returned handle is associated with the object until the object is flushed (TPM2_FlushContext) or
+until the next TPM2_Startup.
+
+For all objects, the size of the key in the sensitive area shall be consistent with the key size indicated in
+the public area or the TPM shall return TPM_RC_KEY_SIZE.
+Before use, a loaded object shall be checked to validate that the public and sensitive portions are
+properly linked, cryptographically. Use of an object includes use in any policy command. If the parts of the
+object are not properly linked, the TPM shall return TPM_RC_BINDING.
+EXAMPLE 1
+
+For a symmetric object, the unique value in the public area shall be the digest of the sensitive key
+and the obfuscation value.
+
+EXAMPLE 2
+
+For a two-prime RSA key, the remainder when dividing the public modulus by the private key shall
+be zero and it shall be possible to form a private exponent from the two prime factors of the public
+modulus.
+
+EXAMPLE 3
+
+For an ECC key, the public point shall be f(x) where x is the private key.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 51
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.2.2 Command and Response
+Table 21 — TPM2_Load Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Load
+
+TPMI_DH_OBJECT
+
+@parentHandle
+
+TPM handle of parent key; shall not be a reserved
+handle
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_PRIVATE
+
+inPrivate
+
+the private portion of the object
+
+TPM2B_PUBLIC
+
+inPublic
+
+the public portion of the object
+
+Table 22 — TPM2_Load Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM_HANDLE
+
+objectHandle
+
+handle for the loaded object
+
+TPM2B_NAME
+
+name
+
+Name of the loaded object
+
+Page 52
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Load_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ASYMMETRIC
+
+storage key with different asymmetric type than parent
+
+TPM_RC_ATTRIBUTES
+
+inPulblic attributes are not allowed with selected parent
+
+TPM_RC_BINDING
+
+inPrivate and inPublic are not cryptographically bound
+
+TPM_RC_HASH
+
+incorrect hash selection for signing key
+
+TPM_RC_INTEGRITY
+
+HMAC on inPrivate was not valid
+
+TPM_RC_KDF
+
+KDF selection not allowed
+
+TPM_RC_KEY
+
+the size of the object's unique field is not consistent with the indicated
+size in the object's parameters
+
+TPM_RC_OBJECT_MEMORY
+
+no available object slot
+
+TPM_RC_SCHEME
+
+the signing scheme is not valid for the key
+
+TPM_RC_SENSITIVE
+
+the inPrivate did not unmarshal correctly
+
+TPM_RC_SIZE
+
+inPrivate missing, or authPolicy size for inPublic or is not valid
+
+TPM_RC_SYMMETRIC
+
+symmetric algorithm not provided when required
+
+TPM_RC_TYPE
+
+parentHandle is not a storage key, or the object to load is a storage
+key but its parameters do not match the parameters of the parent.
+
+TPM_RC_VALUE
+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
+
+Meaning
+
+decryption failure
+
+TPM_RC
+TPM2_Load(
+Load_In *in,
+Load_Out *out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMT_SENSITIVE
+TPMI_RH_HIERARCHY
+OBJECT
+BOOL
+
+result = TPM_RC_SUCCESS;
+sensitive;
+hierarchy;
+*parentObject = NULL;
+skipChecks = FALSE;
+
+// Input Validation
+if(in->inPrivate.t.size == 0)
+return TPM_RC_SIZE + RC_Load_inPrivate;
+parentObject = ObjectGet(in->parentHandle);
+// Is the object that is being used as the parent actually a parent.
+if(!AreAttributesForParent(parentObject))
+return TPM_RC_TYPE + RC_Load_parentHandle;
+// If the parent is fixedTPM, then the attributes of the object
+// are either "correct by construction" or were validated
+// when the object was imported. If they pass the integrity
+// check, then the values are valid
+if(parentObject->publicArea.objectAttributes.fixedTPM)
+skipChecks = TRUE;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 53
+October 31, 2013
+
+ Part 3: Commands
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+Trusted Platform Module Library
+
+else
+{
+// If parent doesn't have fixedTPM SET, then this can't have
+// fixedTPM SET.
+if(in->inPublic.t.publicArea.objectAttributes.fixedTPM == SET)
+return TPM_RC_ATTRIBUTES + RC_Load_inPublic;
+// Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
+// TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
+// TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
+// at this point
+result = PublicAttributesValidation(TRUE, in->parentHandle,
+&in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Load_inPublic);
+}
+// Compute the name of object
+ObjectComputeName(&in->inPublic.t.publicArea, &out->name);
+// Retrieve sensitive data. PrivateToSensitive() may return TPM_RC_INTEGRITY or
+// TPM_RC_SENSITIVE
+// errors may be returned at this point
+result = PrivateToSensitive(&in->inPrivate, &out->name, in->parentHandle,
+in->inPublic.t.publicArea.nameAlg,
+&sensitive);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Load_inPrivate);
+// Internal Data Update
+// Get hierarchy of parent
+hierarchy = ObjectGetHierarchy(in->parentHandle);
+// Create internal object. A lot of different errors may be returned by this
+// loading operation as it will do several validations, including the public
+// binding check
+result = ObjectLoad(hierarchy, &in->inPublic.t.publicArea, &sensitive,
+&out->name, in->parentHandle, skipChecks,
+&out->objectHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+return TPM_RC_SUCCESS;
+}
+
+Page 54
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.3
+
+Part 3: Commands
+
+TPM2_LoadExternal
+
+14.3.1 General Description
+This command is used to load an object that is not a Protected Object into the TPM. The command allows
+loading of a public area or both a public and sensitive area.
+NOTE 1
+
+Typical use for loading a public area is to allow the TPM to validate an asymmetric signature.
+Typical use for loading both a public and sensitive area is to allow the TPM to be used as a crypto
+accelerator.
+
+Load of a public external object area allows the object be associated with a hierarchy so that the correct
+algorithms may be used when creating tickets. The hierarchy parameter provides this association. If the
+public and sensitive portions of the object are loaded, hierarchy is required to be TPM_RH_NULL.
+NOTE 2
+
+If both the public and private portions of an object are loaded, the object is not allowed to appear to
+be part of a hierarchy.
+
+The object’s TPMA_OBJECT attributes will be checked according to the rules defined in
+“TPMA_OBJECT” in Part 2. In particular, fixedTPM, fixedParent, and restricted shall be CLEAR if
+inPrivate is not the Empty Buffer.
+NOTE 3
+
+The duplication status of a public key needs to be able to be the same as the full key which may be
+resident on a different TPM. If both the public and private parts of the key are loaded, then it is not
+possible for the key to be either fixedTPM or fixedParent, since, its private area would not be
+available in the clear to load.
+
+Objects loaded using this command will have a Name. The Name is the nameAlg of the object
+concatenated with the digest of the public area using the nameAlg. The Qualified Name for the object will
+be the same as its Name. The TPM will validate that the authPolicy is either the size of the digest
+produced by nameAlg or the Empty Buffer.
+NOTE 4
+
+If nameAlg is TPM_ALG_NULL, then the Name is the Empty Buffer. When the authorization value for
+an object with no Name is computed, no Name value is included in the HMAC. To ensure that these
+unnamed entities are not substituted, they should have an authValue that is statistically unique.
+
+NOTE 5
+
+The digest size for TPM_ALG_NULL is zero.
+
+If the nameAlg is TPM_ALG_NULL, the TPM shall not verify the cryptographic binding between the public
+and sensitive areas, but the TPM will validate that the size of the key in the sensitive area is consistent
+with the size indicated in the public area. If it is not, the TPM shall return TPM_RC_KEY_SIZE.
+NOTE 6
+
+For an ECC object, the TPM will verify that the public key is on the curve of the key before the public
+area is used.
+
+If nameAlg is not TPM_ALG_NULL, then the same consistency checks between inPublic and inPrivate
+are made as for TPM2_Load().
+NOTE 7
+
+Consistency checks are necessary because an object with a Name needs to have the public and
+sensitive portions cryptographically bound so that an attacker cannot mix pubic and sensitive areas.
+
+The command returns a handle for the loaded object and the Name that the TPM computed for
+inPublic.public (that is, the TPMT_PUBLIC structure in inPublic).
+NOTE 8
+
+The TPM-computed Name is provided as a convenience to the caller for those cases where the
+caller does not implement the hash algorithm specified in the nameAlg of the object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 55
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+The hierarchy parameter associates the external object with a hierarchy. External objects are flushed
+when their associated hierarchy is disabled. If hierarchy is TPM_RH_NULL, the object is part of no
+hierarchy, and there is no implicit flush.
+If hierarchy is TPM_RH_NULL or nameAlg is TPM_ALG_NULL, a ticket produced using the object shall
+be a NULL Ticket.
+EXAMPLE
+
+If a key is loaded with hierarchy set to TPM_RH_NULL, then TPM2_VerifySignature() will produce a
+NULL Ticket of the required type.
+
+External objects are Temporary Objects. The saved external object contexts shall be invalidated at the
+next TPM Reset.
+
+Page 56
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.3.2 Command and Response
+Table 23 — TPM2_LoadExternal Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_LoadExternal
+
+TPM2B_SENSITIVE
+
+inPrivate
+
+the sensitive portion of the object (optional)
+
+TPM2B_PUBLIC+
+
+inPublic
+
+the public portion of the object
+
+TPMI_RH_HIERARCHY+
+
+hierarchy
+
+hierarchy with which the object area is associated
+
+Table 24 — TPM2_LoadExternal Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM_HANDLE
+
+objectHandle
+
+handle for the loaded object
+
+TPM2B_NAME
+
+name
+
+name of the loaded object
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 57
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "LoadExternal_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+'fixedParent" and fixedTPM must be CLEAR on on an external key if
+both public and sensitive portions are loaded
+
+TPM_RC_BINDING
+
+the inPublic and inPrivate structures are not cryptographically bound.
+
+TPM_RC_HASH
+
+incorrect hash selection for signing key
+
+TPM_RC_HIERARCHY
+
+hierarchy is turned off, or only NULL hierarchy is allowed when
+loading public and private parts of an object
+
+TPM_RC_KDF
+
+incorrect KDF selection for decrypting keyedHash object
+
+TPM_RC_KEY
+
+the size of the object's unique field is not consistent with the indicated
+size in the object's parameters
+
+TPM_RC_OBJECT_MEMORY
+
+if there is no free slot for an object
+
+TPM_RC_SCHEME
+
+the signing scheme is not valid for the key
+
+TPM_RC_SIZE
+
+authPolicy is not zero and is not the size of a digest produced by the
+object's nameAlg TPM_RH_NULL hierarchy
+
+TPM_RC_SYMMETRIC
+
+symmetric algorithm not provided when required
+
+TPM_RC_TYPE
+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
+33
+
+Meaning
+
+inPublic and inPrivate are not the same type
+
+TPM_RC
+TPM2_LoadExternal(
+LoadExternal_In
+LoadExternal_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+TPMT_SENSITIVE
+BOOL
+
+result;
+*sensitive;
+skipChecks;
+
+)
+{
+
+// Input Validation
+// If the target hierarchy is turned off, the object can not be loaded.
+if(!HierarchyIsEnabled(in->hierarchy))
+return TPM_RC_HIERARCHY + RC_LoadExternal_hierarchy;
+// the size of authPolicy is either 0 or the digest size of nameAlg
+if(in->inPublic.t.publicArea.authPolicy.t.size != 0
+&& in->inPublic.t.publicArea.authPolicy.t.size !=
+CryptGetHashDigestSize(in->inPublic.t.publicArea.nameAlg))
+return TPM_RC_SIZE + RC_LoadExternal_inPublic;
+// For loading an object with both public and sensitive
+if(in->inPrivate.t.size != 0)
+{
+// An external object can only be loaded at TPM_RH_NULL hierarchy
+if(in->hierarchy != TPM_RH_NULL)
+return TPM_RC_HIERARCHY + RC_LoadExternal_hierarchy;
+// An external object with a sensitive area must have fixedTPM == CLEAR
+// fixedParent == CLEAR, and must have restrict CLEAR so that it does not
+
+Page 58
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+
+Part 3: Commands
+
+// appear to be a key that was created by this TPM.
+if(
+in->inPublic.t.publicArea.objectAttributes.fixedTPM != CLEAR
+|| in->inPublic.t.publicArea.objectAttributes.fixedParent != CLEAR
+|| in->inPublic.t.publicArea.objectAttributes.restricted != CLEAR
+)
+return TPM_RC_ATTRIBUTES + RC_LoadExternal_inPublic;
+}
+// Validate the scheme parameters
+result = SchemeChecks(TRUE, TPM_RH_NULL, &in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_LoadExternal_inPublic);
+// Internal Data Update
+// Need the name to compute the qualified name
+ObjectComputeName(&in->inPublic.t.publicArea, &out->name);
+skipChecks = (in->inPublic.t.publicArea.nameAlg == TPM_ALG_NULL);
+// If a sensitive area was provided, load it
+if(in->inPrivate.t.size != 0)
+sensitive = &in->inPrivate.t.sensitiveArea;
+else
+sensitive = NULL;
+// Create external object. A TPM_RC_BINDING, TPM_RC_KEY, TPM_RC_OBJECT_MEMORY
+// or TPM_RC_TYPE error may be returned by ObjectLoad()
+result = ObjectLoad(in->hierarchy, &in->inPublic.t.publicArea,
+sensitive, &out->name, TPM_RH_NULL, skipChecks,
+&out->objectHandle);
+return result;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 59
+October 31, 2013
+
+ Part 3: Commands
+
+14.4
+
+Trusted Platform Module Library
+
+TPM2_ReadPublic
+
+14.4.1 General Description
+This command allows access to the public area of a loaded object.
+Use of the objectHandle does not require authorization.
+NOTE
+
+Since the caller is not likely to know the public area of the object associated with objectHandle, it
+would not be possible to include the Name associated with objectHandle in the cpHash computation.
+
+If objectHandle references a sequence object, the TPM shall return TPM_RC_SEQUENCE.
+
+Page 60
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.4.2 Command and Response
+Table 25 — TPM2_ReadPublic Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ReadPublic
+
+TPMI_DH_OBJECT
+
+objectHandle
+
+TPM handle of an object
+Auth Index: None
+
+Table 26 — TPM2_ReadPublic Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PUBLIC
+
+outPublic
+
+structure containing the public area of an object
+
+TPM2B_NAME
+
+name
+
+name of the object
+
+TPM2B_NAME
+
+qualifiedName
+
+the Qualified Name of the object
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 61
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "ReadPublic_fp.h"
+Error Returns
+TPM_RC_SEQUENCE
+
+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
+33
+34
+35
+36
+
+Meaning
+can not read the public area of a sequence object
+
+TPM_RC
+TPM2_ReadPublic(
+ReadPublic_In
+ReadPublic_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+OBJECT
+
+*object;
+
+)
+{
+// Input Validation
+// Get loaded object pointer
+object = ObjectGet(in->objectHandle);
+// Can not read public area of a sequence object
+if(ObjectIsSequence(object))
+return TPM_RC_SEQUENCE;
+// Command Output
+// Compute size of public area in canonical form
+out->outPublic.t.size = TPMT_PUBLIC_Marshal(&object->publicArea, NULL, NULL);
+// Copy public area to output
+out->outPublic.t.publicArea = object->publicArea;
+// Copy name to output
+out->name.t.size = ObjectGetName(in->objectHandle, &out->name.t.name);
+// Copy qualified name to output
+ObjectGetQualifiedName(in->objectHandle, &out->qualifiedName);
+return TPM_RC_SUCCESS;
+}
+
+Page 62
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.5
+
+Part 3: Commands
+
+TPM2_ActivateCredential
+
+14.5.1 General Description
+This command enables the association of a credential with an object in a way that ensures that the TPM
+has validated the parameters of the credentialed object.
+If both the public and private portions of activateHandle and keyHandle are not loaded, then the TPM
+shall return TPM_RC_AUTH_UNAVAILABLE.
+If keyHandle is not a Storage Key, then the TPM shall return TPM_RC_TYPE.
+Authorization for activateHandle requires the ADMIN role.
+The key associated with keyHandle is used to recover a seed from secret, which is the encrypted seed.
+The Name of the object associated with activateHandle and the recovered seed are used in a KDF to
+recover the symmetric key. The recovered seed (but not the Name) is used is used in a KDF to recover
+the HMAC key.
+The HMAC is used to validate that the credentialBlob is associated with activateHandle and that the data
+in credentialBlob has not been modified. The linkage to the object associated with activateHandle is
+achieved by including the Name in the HMAC calculation.
+If the integrity checks succeed, credentialBlob is decrypted and returned as certInfo.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 63
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.5.2 Command and Response
+Table 27 — TPM2_ActivateCredential Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+Description
+
+TPM_CC_ActivateCredential
+
+TPMI_DH_OBJECT
+
+@activateHandle
+
+handle of the object associated with certificate in
+credentialBlob
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+loaded key used to decrypt the TPMS_SENSITIVE in
+credentialBlob
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_ID_OBJECT
+
+credentialBlob
+
+the credential
+
+TPM2B_ENCRYPTED_SECRET
+
+secret
+
+keyHandle algorithm-dependent encrypted seed that
+protects credentialBlob
+
+Table 28 — TPM2_ActivateCredential Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+certInfo
+
+Page 64
+October 31, 2013
+
+the decrypted certificate information
+the data should be no larger than the size of the digest
+of the nameAlg associated with keyHandle
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ActivateCredential_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+keyHandle does not reference a decryption key
+
+TPM_RC_ECC_POINT
+
+secret is invalid (when keyHandle is an ECC key)
+
+TPM_RC_INSUFFICIENT
+
+secret is invalid (when keyHandle is an ECC key)
+
+TPM_RC_INTEGRITY
+
+credentialBlob fails integrity test
+
+TPM_RC_NO_RESULT
+
+secret is invalid (when keyHandle is an ECC key)
+
+TPM_RC_SIZE
+
+secret size is invalid or the credentialBlob does not unmarshal
+correctly
+
+TPM_RC_TYPE
+
+keyHandle does not reference an asymmetric key.
+
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+
+Meaning
+
+secret is invalid (when keyHandle is an RSA key)
+
+TPM_RC
+TPM2_ActivateCredential(
+ActivateCredential_In
+ActivateCredential_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+OBJECT
+// credential
+TPM2B_DATA
+
+result = TPM_RC_SUCCESS;
+*object;
+// decrypt key
+*activateObject;// key associated with
+
+)
+{
+
+data;
+
+// credential data
+
+// Input Validation
+// Get decrypt key pointer
+object = ObjectGet(in->keyHandle);
+// Get certificated object pointer
+activateObject = ObjectGet(in->activateHandle);
+// input decrypt key must be an asymmetric, restricted decryption key
+if(
+!CryptIsAsymAlgorithm(object->publicArea.type)
+|| object->publicArea.objectAttributes.decrypt == CLEAR
+|| object->publicArea.objectAttributes.restricted == CLEAR)
+return TPM_RC_TYPE + RC_ActivateCredential_keyHandle;
+// Command output
+// Decrypt input credential data via asymmetric decryption. A
+// TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
+// point
+result = CryptSecretDecrypt(in->keyHandle, NULL,
+"IDENTITY", &in->secret, &data);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_FAILURE;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 65
+October 31, 2013
+
+ Part 3: Commands
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+Trusted Platform Module Library
+
+return RcSafeAddToResult(result, RC_ActivateCredential_secret);
+}
+// Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal
+// errors may be returned at this point
+result = CredentialToSecret(&in->credentialBlob,
+&activateObject->name,
+(TPM2B_SEED *) &data,
+in->keyHandle,
+&out->certInfo);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result,RC_ActivateCredential_credentialBlob);
+return TPM_RC_SUCCESS;
+}
+
+Page 66
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.6
+
+Part 3: Commands
+
+TPM2_MakeCredential
+
+14.6.1 General Description
+This command allows the TPM to perform the actions required of a Certificate Authority (CA) in creating a
+TPM2B_ID_OBJECT containing an activation credential.
+The TPM will produce a TPM_ID_OBJECT according to the methods in “Credential Protection” in Part 1.
+The loaded public area referenced by handle is required to be the public area of a Storage key,
+otherwise, the credential cannot be properly sealed.
+This command does not use any TPM secrets nor does it require authorization. It is a convenience
+function, using the TPM to perform cryptographic calculations that could be done externally.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 67
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.6.2 Command and Response
+Table 29 — TPM2_MakeCredential Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_MakeCredential
+
+TPMI_DH_OBJECT
+
+handle
+
+loaded public area, used to encrypt the sensitive area
+containing the credential key
+Auth Index: None
+
+TPM2B_DIGEST
+
+credential
+
+the credential information
+
+TPM2B_NAME
+
+objectName
+
+Name of the object to which the credential applies
+
+Table 30 — TPM2_MakeCredential Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ID_OBJECT
+
+credentialBlob
+
+TPM2B_ENCRYPTED_SECRET
+
+secret
+
+Page 68
+October 31, 2013
+
+the credential
+handle algorithm-dependent data that wraps the key
+that encrypts credentialBlob
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "MakeCredential_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_KEY
+
+handle referenced an ECC key that has a unique field that is not a
+point on the curve of the key
+
+TPM_RC_SIZE
+
+credential is larger than the digest size of Name algorithm of handle
+
+TPM_RC_TYPE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
+Meaning
+
+handle does not reference an asymmetric decryption key
+
+TPM_RC
+TPM2_MakeCredential(
+MakeCredential_In
+MakeCredential_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+
+result = TPM_RC_SUCCESS;
+
+OBJECT
+TPM2B_DATA
+
+*object;
+data;
+
+)
+{
+
+// Input Validation
+// Get object pointer
+object = ObjectGet(in->handle);
+// input key must be an asymmetric, restricted decryption key
+// NOTE: Needs to be restricted to have a symmetric value.
+if(
+!CryptIsAsymAlgorithm(object->publicArea.type)
+|| object->publicArea.objectAttributes.decrypt == CLEAR
+|| object->publicArea.objectAttributes.restricted == CLEAR
+)
+return TPM_RC_TYPE + RC_MakeCredential_handle;
+// The credential information may not be larger than the digest size used for
+// the Name of the key associated with handle.
+if(in->credential.t.size > CryptGetHashDigestSize(object->publicArea.nameAlg))
+return TPM_RC_SIZE + RC_MakeCredential_credential;
+// Command Output
+// Make encrypt key and its associated secret structure.
+// Even though CrypeSecretEncrypt() may return
+out->secret.t.size = sizeof(out->secret.t.secret);
+result = CryptSecretEncrypt(in->handle, "IDENTITY", &data, &out->secret);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Prepare output credential data from secret
+SecretToCredential(&in->credential, &in->objectName, (TPM2B_SEED *) &data,
+in->handle, &out->credentialBlob);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 69
+October 31, 2013
+
+ Part 3: Commands
+
+14.7
+
+Trusted Platform Module Library
+
+TPM2_Unseal
+
+14.7.1 General Description
+This command returns the data in a loaded Sealed Data Object.
+NOTE
+
+A random, TPM-generated, Sealed Data Object may be created by the TPM with TPM2_Create() or
+TPM2_CreatePrimary() using the template for a Sealed Data Object. A Sealed Data Object is more
+likely to be created externally and imported (TPM2_Import()) so that the data is not created by the
+TPM.
+
+The returned value may be encrypted using authorization session encryption.
+If either restricted, decrypt, or sign is SET in the attributes of itemHandle, then the TPM shall return
+TPM_RC_ATTRIBUTES. If the type of itemHandle is not TPM_ALG_KEYEDHASH, then the TPM shall
+return TPM_RC_TYPE.
+
+Page 70
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.7.2 Command and Response
+Table 31 — TPM2_Unseal Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+Tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Unseal
+
+TPMI_DH_OBJECT
+
+@itemHandle
+
+handle of a loaded data object
+Auth Index: 1
+Auth Role: USER
+
+Description
+
+Table 32 — TPM2_Unseal Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_SENSITIVE_DATA
+
+outData
+
+Family “2.0”
+Level 00 Revision 00.99
+
+unsealed data
+Size of outData is limited to be no more than 128 octets.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 71
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Unseal_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+itemHandle has wrong attributes
+
+TPM_RC_TYPE
+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
+
+Meaning
+
+itemHandle is not a KEYEDHASH data object
+
+TPM_RC
+TPM2_Unseal(Unseal_In *in, Unseal_Out *out)
+{
+OBJECT
+
+*object;
+
+// Input Validation
+// Get pointer to loaded object
+object = ObjectGet(in->itemHandle);
+// Input handle must be a data object
+if(object->publicArea.type != TPM_ALG_KEYEDHASH)
+return TPM_RC_TYPE + RC_Unseal_itemHandle;
+if(
+object->publicArea.objectAttributes.decrypt == SET
+|| object->publicArea.objectAttributes.sign == SET
+|| object->publicArea.objectAttributes.restricted == SET)
+return TPM_RC_ATTRIBUTES + RC_Unseal_itemHandle;
+// Command Output
+// Copy data
+MemoryCopy2B(&out->outData.b, &object->sensitive.sensitive.bits.b,
+sizeof(out->outData.t.buffer));
+return TPM_RC_SUCCESS;
+}
+
+Page 72
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+14.8
+
+Part 3: Commands
+
+TPM2_ObjectChangeAuth
+
+14.8.1 General Description
+This command is used to change the authorization secret for a TPM-resident object.
+If successful, a new private area for the TPM-resident object associated with objectHandle is returned,
+which includes the new authorization value.
+This command does not change the authorization of the TPM-resident object on which it operates.
+Therefore, the old authValue (of the TPM-resident object) is used when generating the response HMAC
+key if required..
+NOTE 1
+
+The returned outPrivate will need to be loaded before the new authorization will apply.
+
+NOTE 2
+
+The TPM-resident object may be persistent and changing the authorization value of the persistent
+object could prevent other users from accessing the object. This is why this command does not
+change the TPM-resident object.
+
+EXAMPLE
+
+If a persistent key is being used as a Storage Root Key and the authorization of the key is a well known value so that the key can be used generally, then changing the authorization value in the
+persistent key would deny access to other users.
+
+This command may not be used to change the authorization value for an NV Index or a Primary Object.
+NOTE 3
+
+If an NV Index is to have a new authorization, it is done with TPM2_NV_ChangeAuth().
+
+NOTE 4
+
+If a Primary Object is to have a new authorization, it needs to be recreated (TPM2_CreatePrimary()).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 73
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+14.8.2 Command and Response
+Table 33 — TPM2_ObjectChangeAuth Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ObjectChangeAuth
+
+TPMI_DH_OBJECT
+
+@objectHandle
+
+handle of the object
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT
+
+parentHandle
+
+handle of the parent
+Auth Index: None
+
+TPM2B_AUTH
+
+newAuth
+
+new authorization value
+
+Table 34 — TPM2_ObjectChangeAuth Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outPrivate
+
+Page 74
+October 31, 2013
+
+private area containing the new authorization value
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+14.8.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ObjectChangeAuth_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+newAuth is larger than the size of the digest of the Name algorithm of
+objectHandle
+
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+the key referenced by parentHandle is not the parent of the object
+referenced by objectHandle; or objectHandle is a sequence object.
+
+TPM_RC
+TPM2_ObjectChangeAuth(
+ObjectChangeAuth_In
+ObjectChangeAuth_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPMT_SENSITIVE
+OBJECT
+TPM2B_NAME
+TPM2B_NAME
+
+sensitive;
+*object;
+objectQN, QNCompare;
+parentQN;
+
+// Input Validation
+// Get object pointer
+object = ObjectGet(in->objectHandle);
+// Can not change auth on sequence object
+if(ObjectIsSequence(object))
+return TPM_RC_TYPE + RC_ObjectChangeAuth_objectHandle;
+// Make sure that the auth value is consistent with the nameAlg
+if( MemoryRemoveTrailingZeros(&in->newAuth)
+> CryptGetHashDigestSize(object->publicArea.nameAlg))
+return TPM_RC_SIZE + RC_ObjectChangeAuth_newAuth;
+// Check parent for object
+// parent handle must be the parent of object handle. In this
+// implementation we verify this by checking the QN of object. Other
+// implementation may choose different method to verify this attribute.
+ObjectGetQualifiedName(in->parentHandle, &parentQN);
+ObjectComputeQualifiedName(&parentQN, object->publicArea.nameAlg,
+&object->name, &QNCompare);
+ObjectGetQualifiedName(in->objectHandle, &objectQN);
+if(!Memory2BEqual(&objectQN.b, &QNCompare.b))
+return TPM_RC_TYPE + RC_ObjectChangeAuth_parentHandle;
+// Command Output
+// Copy internal sensitive area
+sensitive = object->sensitive;
+// Copy authValue
+sensitive.authValue = in->newAuth;
+// Prepare output private data from sensitive
+SensitiveToPrivate(&sensitive, &object->name, in->parentHandle,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 75
+October 31, 2013
+
+ Part 3: Commands
+52
+53
+54
+55
+56
+
+Trusted Platform Module Library
+object->publicArea.nameAlg,
+&out->outPrivate);
+
+return TPM_RC_SUCCESS;
+}
+
+Page 76
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+15
+
+Part 3: Commands
+
+Duplication Commands
+
+15.1
+
+TPM2_Duplicate
+
+15.1.1 General Description
+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 TPM_RH_NULL. Only the public area of
+newParentHandle is required to be loaded.
+NOTE 1
+
+Since the new parent may only be extant on a different TPM, it is likely that the new parent’s
+sensitive area could not be loaded in the TPM from which objectHandle is being duplicated.
+
+If encryptedDuplication is SET in the object being duplicated, then the TPM shall return
+TPM_RC_SYMMETRIC if symmetricAlg is TPM_RH_NULL or TPM_RC_HIERARCHY if
+newParentHandle is TPM_RH_NULL.
+The authorization for this command shall be with a policy session.
+If fixedParent of objectHandle→attributes is SET, the TPM shall return TPM_RC_ATTRIBUTES. If
+objectHandle→nameAlg is TPM_ALG_NULL, the TPM shall return TPM_RC_TYPE.
+The policySession→commandCode parameter in the policy session is required to be TPM_CC_Duplicate
+to indicate that authorization for duplication has been provided. This indicates that the policy that is being
+used is a policy that is for duplication, and not a policy that would approve another use. That is, authority
+to use an object does not grant authority to duplicate the object.
+The policy is likely to include cpHash in order to restrict where duplication can occur.
+If
+TPM2_PolicyCpHash() has been executed as part of the policy, the policySession→cpHash is compared
+to the cpHash of the command.
+If TPM2_PolicyDuplicationSelect() has
+policySession→nameHash is compared to
+
+been
+
+executed
+
+as
+
+part
+
+of
+
+the
+
+policy,
+
+HpolicyAlg(objectHandle→Name || newParentHandle→Name)
+
+the
+(2)
+
+If the compared hashes are not the same, then the TPM shall return TPM_RC_POLICY_FAIL.
+NOTE 2
+
+It is allowed that policySesion→nameHash and policySession→cpHash share the same memory
+space.
+
+NOTE 3
+
+A duplication policy is not required to have either TPM2_PolicyDuplicationSelect() or
+TPM2_PolicyCpHash() as part of the policy. If neither is present, then the duplication policy may be
+satisfied with a policy that only contains TPM2_PolicyCommaneCode( code = TPM_CC_Duplicate).
+
+The TPM shall follow the process of encryption defined in the “Duplication” subclause of “Protected
+Storage Hierarchy” in Part 1 of this specification.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 77
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+15.1.2 Command and Response
+Table 35 — TPM2_Duplicate Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Duplicate
+
+TPMI_DH_OBJECT
+
+@objectHandle
+
+loaded object to duplicate
+Auth Index: 1
+Auth Role: DUP
+
+TPMI_DH_OBJECT+
+
+newParentHandle
+
+shall reference the public area of an asymmetric key
+Auth Index: None
+
+TPM2B_DATA
+
+encryptionKeyIn
+
+optional symmetric encryption key
+The size for this key is set to zero when the TPM is to
+generate the key. This parameter may be encrypted.
+
+TPMT_SYM_DEF_OBJECT+
+
+symmetricAlg
+
+definition for the symmetric algorithm to be used for the
+inner wrapper
+may be TPM_ALG_NULL if no inner wrapper is applied
+
+Table 36 — TPM2_Duplicate Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DATA
+
+encryptionKeyOut
+
+If the caller provided an encryption key or if
+symmetricAlg was TPM_ALG_NULL, then this will be
+the Empty Buffer; otherwise, it shall contain the TPMgenerated, symmetric encryption key for the inner
+wrapper.
+
+TPM2B_PRIVATE
+
+duplicate
+
+private area that may be encrypted by encryptionKeyIn;
+and may be doubly encrypted
+
+TPM2B_ENCRYPTED_SECRET
+
+outSymSeed
+
+Page 78
+October 31, 2013
+
+seed protected by the asymmetric algorithms of new
+parent (NP)
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+15.1.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Duplicate_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key to duplicate has fixedParent SET
+
+TPM_RC_HIERARCHY
+
+encryptedDuplication is SET and newParentHandle specifies Null
+Hierarchy
+
+TPM_RC_KEY
+
+newParentHandle references invalid ECC key (public point not on the
+curve)
+
+TPM_RC_SIZE
+
+input encryption key size does not match the size specified in
+symmetric algorithm
+
+TPM_RC_SYMMETRIC
+
+encryptedDuplication is SET but no symmetric algorithm is provided
+
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
+Meaning
+
+newParentHandle is neither a storage key nor TPM_RH_NULL; or
+the object has a NULL nameAlg
+
+TPM_RC
+TPM2_Duplicate(
+Duplicate_In
+Duplicate_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMT_SENSITIVE
+
+result = TPM_RC_SUCCESS;
+sensitive;
+
+UINT16
+
+innerKeySize = 0; // encrypt key size for inner wrap
+
+OBJECT
+TPM2B_DATA
+
+*object;
+data;
+
+// Input Validation
+// Get duplicate object pointer
+object = ObjectGet(in->objectHandle);
+// duplicate key must have fixParent bit CLEAR.
+if(object->publicArea.objectAttributes.fixedParent == SET)
+return TPM_RC_ATTRIBUTES + RC_Duplicate_objectHandle;
+// Do not duplicate object with NULL nameAlg
+if(object->publicArea.nameAlg == TPM_ALG_NULL)
+return TPM_RC_TYPE + RC_Duplicate_objectHandle;
+// new parent key must be a storage object or TPM_RH_NULL
+if(in->newParentHandle != TPM_RH_NULL
+&& !ObjectIsStorage(in->newParentHandle))
+return TPM_RC_TYPE + RC_Duplicate_newParentHandle;
+// If the duplicates object has encryptedDuplication SET, then there must be
+// an inner wrapper and the new parent may not be TPM_RH_NULL
+if(object->publicArea.objectAttributes.encryptedDuplication == SET)
+{
+if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
+return TPM_RC_SYMMETRIC + RC_Duplicate_symmetricAlg;
+if(in->newParentHandle == TPM_RH_NULL)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 79
+October 31, 2013
+
+ Part 3: Commands
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+
+Trusted Platform Module Library
+
+return TPM_RC_HIERARCHY + RC_Duplicate_newParentHandle;
+}
+if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
+{
+// if algorithm is TPM_ALG_NULL, input key size must be 0
+if(in->encryptionKeyIn.t.size != 0)
+return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
+}
+else
+{
+// Get inner wrap key size
+innerKeySize = in->symmetricAlg.keyBits.sym;
+// If provided the input symmetric key must match the size of the algorithm
+if(in->encryptionKeyIn.t.size != 0
+&& in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
+return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
+}
+// Command Output
+if(in->newParentHandle != TPM_RH_NULL)
+{
+// Make encrypt key and its associated secret structure. A TPM_RC_KEY
+// error may be returned at this point
+out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
+result = CryptSecretEncrypt(in->newParentHandle,
+"DUPLICATE", &data, &out->outSymSeed);
+pAssert(result != TPM_RC_VALUE);
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+else
+{
+// Do not apply outer wrapper
+data.t.size = 0;
+out->outSymSeed.t.size = 0;
+}
+// Copy sensitive area
+sensitive = object->sensitive;
+// Prepare output private data from sensitive
+SensitiveToDuplicate(&sensitive, &object->name, in->newParentHandle,
+object->publicArea.nameAlg, (TPM2B_SEED *) &data,
+&in->symmetricAlg, &in->encryptionKeyIn,
+&out->duplicate);
+out->encryptionKeyOut = in->encryptionKeyIn;
+return TPM_RC_SUCCESS;
+}
+
+Page 80
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+15.2
+
+Part 3: Commands
+
+TPM2_Rewrap
+
+15.2.1 General Description
+This command allows the TPM to serve in the role as a Duplication Authority. If proper authorization for
+use of the oldParent is provided, then an HMAC key and a symmetric key are recovered from inSymSeed
+and used to integrity check and decrypt inDuplicate. A new protection seed value is generated according
+to the methods appropriate for newParent and the blob is re-encrypted and a new integrity value is
+computed. The re-encrypted blob is returned in outDuplicate and the symmetric key returned in
+outSymKey.
+In the rewrap process, L is “DUPLICATE” (see “Terms and Definitions” in Part 1).
+If inSymSeed has a zero length, then oldParent is required to be TPM_RH_NULL and no decryption of
+inDuplicate takes place.
+If newParent is TPM_RH_NULL, then no encryption is performed on outDuplicate. outSymSeed will have
+a zero length. See Part 2 encryptedDuplication.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 81
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+15.2.2 Command and Response
+Table 37 — TPM2_Rewrap Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Rewrap
+
+TPMI_DH_OBJECT+
+
+@oldParent
+
+parent of object
+Auth Index: 1
+Auth Role: User
+
+TPMI_DH_OBJECT+
+
+newParent
+
+new parent of the object
+Auth Index: None
+
+TPM2B_PRIVATE
+
+inDuplicate
+
+an object encrypted using symmetric key derived from
+inSymSeed
+
+TPM2B_NAME
+
+name
+
+the Name of the object being rewrapped
+
+TPM2B_ENCRYPTED_SECRET
+
+inSymSeed
+
+Description
+
+seed for symmetric key
+needs oldParent private key to recover the seed and
+generate the symmetric key
+
+Table 38 — TPM2_Rewrap Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outDuplicate
+
+TPM2B_ENCRYPTED_SECRET
+
+outSymSeed
+
+Page 82
+October 31, 2013
+
+an object encrypted using symmetric key derived from
+outSymSeed
+seed for a symmetric key protected by newParent
+asymmetric key
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+15.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Rewrap_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+newParent is not a decryption key
+
+TPM_RC_HANDLE
+
+oldParent does not consistent with inSymSeed
+
+TPM_RC_INTEGRITY
+
+the integrity check of inDuplicate failed
+
+TPM_RC_KEY
+
+for an ECC key, the public key is not on the curve of the curve ID
+
+TPM_RC_KEY_SIZE
+
+the decrypted input symmetric key size does not matches the
+symmetric algorithm key size of oldParent
+
+TPM_RC_TYPE
+
+oldParent is not a storage key, or 'newParent is not a storage key
+
+TPM_RC_VALUE
+
+for an 'oldParent; RSA key, the data to be decrypted is greater than
+the public exponent
+
+Unmarshal errors
+
+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
+33
+34
+35
+36
+37
+38
+39
+
+Meaning
+
+errors during unmarshaling the input encrypted buffer to a ECC public
+key, or unmarshal the private buffer to sensitive
+
+TPM_RC
+TPM2_Rewrap(
+Rewrap_In
+Rewrap_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+TPM2B_DATA
+UINT16
+TPM2B_PRIVATE
+
+result = TPM_RC_SUCCESS;
+*oldParent;
+data;
+// symmetric key
+hashSize = 0;
+privateBlob;
+// A temporary private blob
+// to transit between old
+// and new wrappers
+
+)
+{
+
+// Input Validation
+if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL)
+|| (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL))
+return TPM_RC_HANDLE + RC_Rewrap_oldParent;
+if(in->oldParent != TPM_RH_NULL)
+{
+// Get old parent pointer
+oldParent = ObjectGet(in->oldParent);
+// old parent key must be a storage object
+if(!ObjectIsStorage(in->oldParent))
+return TPM_RC_TYPE + RC_Rewrap_oldParent;
+// Decrypt input secret data via asymmetric decryption. A
+// TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
+// point
+result = CryptSecretDecrypt(in->oldParent, NULL,
+"DUPLICATE", &in->inSymSeed, &data);
+if(result != TPM_RC_SUCCESS)
+return TPM_RC_VALUE + RC_Rewrap_inSymSeed;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 83
+October 31, 2013
+
+ Part 3: Commands
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
+Trusted Platform Module Library
+
+// Unwrap Outer
+result = UnwrapOuter(in->oldParent, &in->name,
+oldParent->publicArea.nameAlg, (TPM2B_SEED *) &data,
+FALSE,
+in->inDuplicate.t.size, in->inDuplicate.t.buffer);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Rewrap_inDuplicate);
+// Copy unwrapped data to temporary variable, remove the integrity field
+hashSize = sizeof(UINT16) +
+CryptGetHashDigestSize(oldParent->publicArea.nameAlg);
+privateBlob.t.size = in->inDuplicate.t.size - hashSize;
+MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize,
+privateBlob.t.size, sizeof(privateBlob.t.buffer));
+}
+else
+{
+// No outer wrap from input blob.
+privateBlob = in->inDuplicate;
+}
+
+Direct copy.
+
+if(in->newParent != TPM_RH_NULL)
+{
+OBJECT
+*newParent;
+newParent = ObjectGet(in->newParent);
+// New parent must be a storage object
+if(!ObjectIsStorage(in->newParent))
+return TPM_RC_TYPE + RC_Rewrap_newParent;
+// Make new encrypt key and its associated secret structure. A
+// TPM_RC_VALUE error may be returned at this point if RSA algorithm is
+// enabled in TPM
+out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
+result = CryptSecretEncrypt(in->newParent,
+"DUPLICATE", &data, &out->outSymSeed);
+if(result != TPM_RC_SUCCESS) return result;
+// Command output
+// Copy temporary variable to output, reserve the space for integrity
+hashSize = sizeof(UINT16) +
+CryptGetHashDigestSize(newParent->publicArea.nameAlg);
+out->outDuplicate.t.size = privateBlob.t.size;
+MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer,
+privateBlob.t.size, sizeof(out->outDuplicate.t.buffer));
+// Produce outer wrapper for output
+out->outDuplicate.t.size = ProduceOuterWrap(in->newParent, &in->name,
+newParent->publicArea.nameAlg,
+(TPM2B_SEED *) &data,
+FALSE,
+out->outDuplicate.t.size,
+out->outDuplicate.t.buffer);
+}
+else // New parent is a null key so there is no seed
+{
+out->outSymSeed.t.size = 0;
+// Copy privateBlob directly
+out->outDuplicate = privateBlob;
+}
+
+Page 84
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+104
+105
+
+Part 3: Commands
+
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 85
+October 31, 2013
+
+ Part 3: Commands
+
+15.3
+
+Trusted Platform Module Library
+
+TPM2_Import
+
+15.3.1 General Description
+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.
+If fixedTPM or fixedParent is SET in objectPublic, the TPM shall return TPM_RC_ATTRIBUTES.
+If encryptedDuplication is SET in the object referenced by parentHandle, then encryptedDuplication shall
+be set in objectPublic (TPM_RC_ATTRIBUTES). However, see Note 2.
+Recovery of the sensitive data of the object occurs in the TPM in a three-step process in the following
+order:
+
+
+If present, the outer layer of symmetric encryption is removed. If inSymSeed has a non-zero size, the
+asymmetric parameters and private key of parentHandle are used to recover the seed used in the
+creation of the HMAC key and encryption keys used to protect the duplication blob. When recovering
+the seed, L is “DUPLICATE”.
+NOTE 1
+
+If the encryptedDuplication attribute of the object
+TPM_RC_ATTRIBUTES if inSymSeed is an empty buffer.
+
+is
+
+SET,
+
+the
+
+TPM
+
+shall
+
+return
+
+
+
+If present, the inner layer of symmetric encryption is removed. If encryptionKey and symmetricAlg are
+provided, they are used to decrypt duplication.
+
+
+
+If present, the integrity value of the blob is checked. The presence of the integrity value is indicated
+by a non-zero value for duplicate.data.integrity.size. The integrity of the private area is validated using
+the Name of objectPublic in the integrity HMAC computation. If either the outer layer or inner layer of
+encryption is performed, then the integrity value shall be present.
+
+If the inner or outer wrapper is present, then a valid integrity value shall be present or the TPM shall
+return TPM_RC_INTEGRITY.
+NOTE 2
+
+It is not necessary to validate that the sensitive area data is cryptographically bound to the public
+area other than that the Name of the public area is included in the HMAC. However, if the binding is
+not validated by this command, the binding must be checked each time the object is loaded. For an
+object that is imported under a parent with fixedTPM SET, binding need only be checked at import. If
+the parent has fixedTPM CLEAR, then the binding needs to be checked each time the object is
+loaded, or before the TPM performs an operation for which the binding affects the outcome of the
+operation (for example, TPM2_PolicySigned() or TPM2_Certify()).
+Similarly, if the new parent's fixedTPM is set, the encryptedDuplication state need only be checked
+at import.
+If the new parent is not fixedTPM, then that object will be loadable on any TPM (including SW
+versions) on which the new parent exists. This means that, each time an object is loaded under a
+parent that is not fixedTPM, it is necessary to validate all of the properties of that object. If the
+parent is fixedTPM, then the new private blob is integrity protected by the TPM that “owns” the
+parent. So, it is sufficient to validate the object’s properties (attribute and public -private binding) on
+import and not again.
+
+Before duplicate.buffer is decrypted using the symmetric key of the parent, the integrity value shall be
+checked before the sensitive area is used, or unmarshaled.
+After integrity checks and decryption, the TPM will create a new symmetrically encrypted private area
+using the encryption key of the parent.
+NOTE 3
+
+Checking the integrity before the data is used prevents attacks on the sensitive area by fuzzing the
+data and looking at the differences in the response codes.
+
+Page 86
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+NOTE 4
+
+Part 3: Commands
+
+The symmetric re-encryption is the normal integrity generation and symmetric encryption applied to
+a child object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 87
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+15.3.2 Command and Response
+Table 39 — TPM2_Import Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Import
+
+TPMI_DH_OBJECT
+
+@parentHandle
+
+the handle of the new parent for the object
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DATA
+
+encryptionKey
+
+the optional symmetric encryption key used as the inner
+wrapper for duplicate
+If symmetricAlg is TPM_ALG_NULL, then this
+parameter shall be the Empty Buffer.
+
+TPM2B_PUBLIC
+
+objectPublic
+
+Description
+
+the public area of the object to be imported
+This is provided so that the integrity value for duplicate
+and the object attributes can be checked.
+NOTE
+
+TPM2B_PRIVATE
+
+duplicate
+
+Even if the integrity value of the object is not
+checked on input, the object Name is required to
+create the integrity value for the imported object.
+
+the symmetrically encrypted duplicate object that may
+contain an inner symmetric wrapper
+
+TPM2B_ENCRYPTED_SECRET
+inSymSeed
+
+symmetric key used to encrypt duplicate
+inSymSeed is encrypted/encoded using the algorithms
+of newParent.
+
+TPMT_SYM_DEF_OBJECT+
+
+symmetricAlg
+
+definition for the symmetric algorithm to use for the inner
+wrapper
+If this algorithm is TPM_ALG_NULL, no inner wrapper is
+present and encryptionKey shall be the Empty Buffer.
+
+Table 40 — TPM2_Import Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PRIVATE
+
+outPrivate
+
+Page 88
+October 31, 2013
+
+the sensitive area encrypted with the symmetric key of
+parentHandle
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+15.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Import_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+
+Meaning
+
+TPM_RC_ASYMMETRIC
+
+non-duplicable storage key represented by objectPublic and its
+parent referenced by parentHandle have different public params
+
+TPM_RC_ATTRIBUTES
+
+attributes FixedTPM and fixedParent of objectPublic are not both
+CLEAR; or inSymSeed is nonempty and parentHandle does not
+reference a decryption key; or objectPublic and parentHandle have
+incompatible or inconsistent attributes
+
+TPM_RC_BINDING
+
+duplicate and objectPublic are not cryptographically bound
+
+TPM_RC_ECC_POINT
+
+inSymSeed is nonempty and ECC point in inSymSeed is not on the
+curve
+
+TPM_RC_HASH
+
+non-duplicable storage key represented by objectPublic and its
+parent referenced by parentHandle have different name algorithm
+
+TPM_RC_INSUFFICIENT
+
+inSymSeed is nonempty and failed to retrieve ECC point from the
+secret; or unmarshaling sensitive value from duplicate failed the
+result of inSymSeed decryption
+
+TPM_RC_INTEGRITY
+
+duplicate integrity is broken
+
+TPM_RC_KDF
+
+objectPublic representing decrypting keyed hash object specifies
+invalid KDF
+
+TPM_RC_KEY
+
+inconsistent parameters of objectPublic; or inSymSeed is nonempty
+and parentHandle does not reference a key of supported type; or
+invalid key size in objectPublic representing an asymmetric key
+
+TPM_RC_NO_RESULT
+
+inSymSeed is nonempty and multiplication resulted in ECC point at
+infinity
+
+TPM_RC_OBJECT_MEMORY
+
+no available object slot
+
+TPM_RC_SCHEME
+
+inconsistent attributes decrypt, sign, restricted and key's scheme ID
+in objectPublic; or hash algorithm is inconsistent with the scheme ID
+for keyed hash object
+
+TPM_RC_SIZE
+
+authPolicy size does not match digest size of the name algorithm in
+objectPublic; or symmetricAlg and encryptionKey have different
+sizes; or inSymSeed is nonempty and it is not of the same size as
+RSA key referenced by parentHandle; or unmarshaling sensitive
+value from duplicate failed
+
+TPM_RC_SYMMETRIC
+
+objectPublic is either a storage key with no symmetric algorithm or a
+non-storage key with symmetric algorithm different from
+TPM_ALG_NULL
+
+TPM_RC_TYPE
+
+unsupported type of objectPublic; or non-duplicable storage key
+represented by objectPublic and its parent referenced by
+parentHandle are of different types; or parentHandle is not a storage
+key; or only the public portion of parentHandle is loaded; or
+objectPublic and duplicate are of different types
+
+TPM_RC_VALUE
+
+nonempty inSymSeed and its numeric value is greater than the
+modulus of the key referenced by parentHandle or inSymSeed is
+larger than the size of the digest produced by the name algorithm of
+the symmetric key referenced by parentHandle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 89
+October 31, 2013
+
+ Part 3: Commands
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+
+Trusted Platform Module Library
+
+TPM_RC
+TPM2_Import(
+Import_In
+Import_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+OBJECT
+TPM2B_DATA
+TPMT_SENSITIVE
+TPM2B_NAME
+
+result = TPM_RC_SUCCESS;
+*parentObject;
+data;
+// symmetric key
+sensitive;
+name;
+
+UINT16
+
+innerKeySize = 0;
+
+// encrypt key size for inner
+// wrapper
+
+// Input Validation
+// FixedTPM and fixedParent must be CLEAR
+if(
+in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET
+|| in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET)
+return TPM_RC_ATTRIBUTES + RC_Import_objectPublic;
+// Get parent pointer
+parentObject = ObjectGet(in->parentHandle);
+if(!AreAttributesForParent(parentObject))
+return TPM_RC_TYPE + RC_Import_parentHandle;
+if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
+{
+// Get inner wrap key size
+innerKeySize = in->symmetricAlg.keyBits.sym;
+// Input symmetric key must match the size of algorithm.
+if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
+return TPM_RC_SIZE + RC_Import_encryptionKey;
+}
+else
+{
+// If input symmetric algorithm is NULL, input symmetric key size must
+// be 0 as well
+if(in->encryptionKey.t.size != 0)
+return TPM_RC_SIZE + RC_Import_encryptionKey;
+}
+// See if there is an outer wrapper
+if(in->inSymSeed.t.size != 0)
+{
+// Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
+// TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
+// TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
+result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE",
+&in->inSymSeed, &data);
+pAssert(result != TPM_RC_BINDING);
+if(result != TPM_RC_SUCCESS)
+return TPM_RC_VALUE + RC_Import_inSymSeed;
+}
+else
+{
+data.t.size = 0;
+}
+// Compute name of object
+ObjectComputeName(&(in->objectPublic.t.publicArea), &name);
+
+Page 90
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+
+Part 3: Commands
+
+// Retrieve sensitive from private.
+// TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
+result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle,
+in->objectPublic.t.publicArea.nameAlg,
+(TPM2B_SEED *) &data, &in->symmetricAlg,
+&in->encryptionKey, &sensitive);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Import_duplicate);
+// If the parent of this object has fixedTPM SET, then fully validate this
+// object so that validation can be skipped when it is loaded
+if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
+{
+TPM_HANDLE
+objectHandle;
+// Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
+// TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
+// TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
+// at this point
+result = PublicAttributesValidation(TRUE, in->parentHandle,
+&in->objectPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_Import_objectPublic);
+// Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or
+// TPM_RC_OBJECT_MEMORY error may be returned at this point
+result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea,
+&sensitive, NULL, in->parentHandle, FALSE,
+&objectHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Don't need the object, just needed the checks to be performed so
+// flush the object
+ObjectFlush(objectHandle);
+}
+// Command output
+// Prepare output private data from sensitive
+SensitiveToPrivate(&sensitive, &name, in->parentHandle,
+in->objectPublic.t.publicArea.nameAlg,
+&out->outPrivate);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 91
+October 31, 2013
+
+ Part 3: Commands
+
+16
+
+Trusted Platform Module Library
+
+Asymmetric Primitives
+
+16.1
+
+Introduction
+
+The commands in this clause provide low-level primitives for access to the asymmetric algorithms
+implemented in the TPM. Many of these commands are only allowed if the asymmetric key is an
+unrestricted key.
+16.2
+
+TPM2_RSA_Encrypt
+
+16.2.1 General Description
+This command performs RSA encryption using the indicated padding scheme according to PKCS#1v2.1
+(PKCS#1). If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use inScheme to specify
+the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, then inScheme shall either be
+TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME).
+The key referenced by keyHandle is required to be an RSA key (TPM_RC_KEY) with the decrypt attribute
+SET (TPM_RC_ATTRIBUTES).
+NOTE
+
+Requiring that the decrypt attribute be set allows the TPM to ensure that the scheme selection is
+done with the presumption that the scheme of the key is a decryption scheme selection. It is
+understood that this command will operate on a key with only the publi c part loaded so the caller
+may modify any key in any desired way. So, this constraint only serves to simplify the TPM logic.
+
+The three types of allowed padding are:
+1) TPM_ALG_OAEP – Data is OAEP padded as described in 7.1 of PKCS#1 v2.1. The only
+supported mask generation is MGF1.
+2) TPM_ALG_RSAES – Data is padded as described in 7.2 of PKCS#1 v2.1.
+3) TPM_ALG_NULL – Data is not padded by the TPM and the TPM will treat message as an
+unsigned integer and perform a modular exponentiation of message using the public
+exponent of the key referenced by keyHandle. This scheme is only used if both the scheme
+in the key referenced by keyHandle is TPM_ALG_NULL, and the inScheme parameter of the
+command is TPM_ALG_NULL. The input value cannot be larger than the public modulus of
+the key referenced by keyHandle.
+Table 41 — Padding Scheme Selection
+keyHandle→scheme
+
+OAEP
+RSAES
+
+TPM_ALG_RSAES
+
+RSAES
+error (TPM_RC_SCHEME)
+
+TPM_ALG_NULL
+
+OAEP
+
+TPM_ALG_RSAES
+
+error (TPM_RC_SCHEME)
+
+TPM_AGL_OAEP
+
+October 31, 2013
+
+RSAES
+
+TPM_ALG_OAEP
+
+Page 92
+
+TPM_ALG_RSAES
+
+TPM_ALG_NULL
+
+TPM_ALG_OAEP
+
+none
+
+TPM_ALG_OAEP
+
+TPM_ALG_RSAES
+
+padding scheme used
+
+TPM_ALG_NULL
+TPM_ALG_NULL
+
+inScheme
+
+OAEP
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+After padding, the data is RSAEP encrypted according to 5.1.1 of PKCS#1v2.1.
+NOTE 1
+
+It is required that decrypt be SET so that the commands that load a key can validate that the
+scheme is consistent rather than have that deferred until the key is used.
+
+NOTE 2
+
+If it is desired to use a key that had restricted SET, the caller may CLEAR restricted and load the
+public part of the key and use that unrestricted version of the key for encryption.
+
+If inScheme is used, and the scheme requires a hash algorithm it may not be TPM_ALG_NULL.
+NOTE 3
+
+Because only the public portion of the key needs to be loaded for this command, the caller can
+manipulate the attributes of the key in any way desired. As a result , the TPM shall not check the
+consistency of the attributes. The only property checking is that the key is an RSA key and that the
+padding scheme is supported.
+
+The message parameter is limited in size by the padding scheme according to the following table:
+Table 42 — Message Size Limits Based on Padding
+Scheme
+
+Maximum Message Length
+(mLen) in Octets
+
+TPM_ALG_OAEP
+
+mLen  k – 2hLen – 2
+
+TPM_ALG_RSAES
+
+mLen  k – 11
+
+TPM_ALG_NULL
+
+mLen  k
+
+Comments
+
+The numeric value of the message must be
+less than the numeric value of the public
+modulus (n).
+
+NOTES
+1)
+2)
+
+k ≔ the number of byes in the public modulus
+hLen ≔ the number of octets in the digest produced by the hash algorithm used in the process
+
+The label parameter is optional. If provided (label.size != 0) then the TPM shall return TPM_RC_VALUE if
+the last octet in label is not zero. If a zero octet occurs before label.buffer[label.size-1], the TPM shall
+truncate the label at that point. The terminating octet of zero is included in the label used in the padding
+scheme.
+NOTE 4
+
+If the scheme does not use a label, the TPM will still verify that label is properly formatted if label is
+present.
+
+The function returns padded and encrypted value outData.
+The message parameter in the command may be encrypted using parameter encryption.
+NOTE 5
+
+Only the public area of keyHandle is required to be loaded. A public key may be loaded with any
+desired scheme. If the scheme is to be changed, a different public area must be loaded.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 93
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.2.2 Command and Response
+Table 43 — TPM2_RSA_Encrypt Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_RSA_Encrypt
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+reference to public portion of RSA key to use for
+encryption
+Auth Index: None
+message to be encrypted
+
+TPM2B_PUBLIC_KEY_RSA
+
+message
+
+TPMT_RSA_DECRYPT+
+
+inScheme
+
+TPM2B_DATA
+
+label
+
+NOTE 1
+
+The data type was chosen because it limits the
+overall size of the input to no greater than the size
+of the largest RSA public key. This may be larger
+than allowed for keyHandle.
+
+the padding scheme to use if scheme associated with
+keyHandle is TPM_ALG_NULL
+optional label L to be associated with the message
+Size of the buffer is zero if no label is present
+NOTE 2
+
+See description of label above.
+
+Table 44 — TPM2_RSA_Encrypt Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PUBLIC_KEY_RSA
+
+outData
+
+Page 94
+October 31, 2013
+
+encrypted output
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "RSA_Encrypt_fp.h"
+#ifdef TPM_ALG_RSA
+Error Returns
+TPM_RC_ATTRIBUTES
+
+decrypt attribute is not SET in key referenced by keyHandle
+
+TPM_RC_KEY
+
+keyHandle does not reference an RSA key
+
+TPM_RC_SCHEME
+
+incorrect input scheme, or the chosen scheme is not a valid RSA
+decrypt scheme
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+the numeric value of message is greater than the public modulus of
+the key referenced by keyHandle, or label is not a null-terminated
+string
+
+TPM_RC
+TPM2_RSA_Encrypt(
+RSA_Encrypt_In
+RSA_Encrypt_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+TPMT_RSA_DECRYPT
+char
+
+result;
+*rsaKey;
+*scheme;
+*label = NULL;
+
+)
+{
+
+// Input Validation
+rsaKey = ObjectGet(in->keyHandle);
+// selected key must be an RSA key
+if(rsaKey->publicArea.type != TPM_ALG_RSA)
+return TPM_RC_KEY + RC_RSA_Encrypt_keyHandle;
+// selected key must have the decryption attribute
+if(rsaKey->publicArea.objectAttributes.decrypt != SET)
+return TPM_RC_ATTRIBUTES + RC_RSA_Encrypt_keyHandle;
+// Is there a label?
+if(in->label.t.size > 0)
+{
+// label is present, so make sure that is it NULL-terminated
+if(in->label.t.buffer[in->label.t.size - 1] != 0)
+return TPM_RC_VALUE + RC_RSA_Encrypt_label;
+label = (char *)in->label.t.buffer;
+}
+// Command Output
+// Select a scheme for encryption
+scheme = CryptSelectRSAScheme(in->keyHandle, &in->inScheme);
+if(scheme == NULL)
+return TPM_RC_SCHEME + RC_RSA_Encrypt_inScheme;
+// Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy
+// CryptEncyptRSA. Note: It can also return TPM_RC_ATTRIBUTES if the key does
+// not have the decrypt attribute but that was checked above.
+out->outData.t.size = sizeof(out->outData.t.buffer);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 95
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+
+Trusted Platform Module Library
+
+result = CryptEncryptRSA(&out->outData.t.size, out->outData.t.buffer, rsaKey,
+scheme, in->message.t.size, in->message.t.buffer,
+label);
+return result;
+}
+#endif
+
+Page 96
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.3
+
+Part 3: Commands
+
+TPM2_RSA_Decrypt
+
+16.3.1 General Description
+This command performs RSA decryption using the indicated padding scheme according to PKCS#1v2.1
+(PKCS#1).
+The scheme selection for this command is the same as for TPM2_RSA_Encrypt() and is shown in Table
+41.
+The key referenced by keyHandle shall be an RSA key (TPM_RC_KEY) with restricted CLEAR and
+decrypt SET (TPM_RC_ATTRIBUTES).
+This command uses the private key of keyHandle for this operation and authorization is required.
+The TPM will perform a modular exponentiation of ciphertext using the private exponent associated with
+keyHandle (this is described in PKCS#1v2.1, clause 5.1.2). It will then validate the padding according to
+the selected scheme. If the padding checks fail, TPM_RC_VALUE is returned. Otherwise, the data is
+returned with the padding removed. If no padding is used, the returned value is an unsigned integer value
+that is the result of the modular exponentiation of cipherText using the private exponent of keyHandle.
+The returned value may include leading octets zeros so that it is the same size as the public modulus. For
+the other padding schemes, the returned value will be smaller than the public modulus but will contain all
+the data remaining after padding is removed and this may include leading zeros if the original encrypted
+value contained leading zeros..
+If a label is used in the padding process of the scheme, the label parameter is required to be present in
+the decryption process and label is required to be the same in both cases. The TPM shall verify that the
+label is consistent and if not it shall return TPM_RC_VALUE.
+If label is present (label.size != 0), it
+shall be a NULL-terminated string or the TPM will return TPM_RC_VALUE.
+NOTE 1
+
+The size of label includes the terminating null.
+
+The message parameter in the response may be encrypted using parameter encryption.
+If the decryption scheme does not require a hash function, the hash parameter of inScheme may be set
+to any valid hash function or TPM_ALG_NULL.
+If the description scheme does not require a label, the value in label is not used but the size of the label
+field is checked for consistency with the indicated data type (TPM2B_DATA). That is, the field may not be
+larger than allowed for a TPM2B_DATA.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 97
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.3.2 Command and Response
+Table 45 — TPM2_RSA_Decrypt Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_RSA_Decrypt
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+RSA key to use for decryption
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_PUBLIC_KEY_RSA
+
+cipherText
+
+NOTE
+
+TPMT_RSA_DECRYPT+
+
+inScheme
+
+the padding scheme to use if scheme associated with
+keyHandle is TPM_ALG_NULL
+
+TPM2B_DATA
+
+label
+
+label whose association with the message is to be
+verified
+
+cipher text to be decrypted
+An encrypted RSA data block is the size of the
+public modulus.
+
+Table 46 — TPM2_RSA_Decrypt Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_PUBLIC_KEY_RSA
+
+message
+
+Page 98
+October 31, 2013
+
+decrypted output
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "RSA_Decrypt_fp.h"
+#ifdef TPM_ALG_RSA
+Error Returns
+TPM_RC_KEY
+
+keyHandle does not reference an unrestricted decrypt key
+
+TPM_RC_SCHEME
+
+incorrect input scheme, or the chosen scheme is not a valid RSA
+decrypt scheme
+
+TPM_RC_SIZE
+
+cipherText is not the size of the modulus of key referenced by
+keyHandle
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+label is not a null terminated string or the value of cipherText is
+greater that the modulus of keyHandle
+
+TPM_RC
+TPM2_RSA_Decrypt(
+RSA_Decrypt_In
+RSA_Decrypt_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+OBJECT
+TPMT_RSA_DECRYPT
+char
+
+result;
+*rsaKey;
+*scheme;
+*label = NULL;
+
+)
+{
+
+// Input Validation
+rsaKey = ObjectGet(in->keyHandle);
+// The selected key must be an RSA key
+if(rsaKey->publicArea.type != TPM_ALG_RSA)
+return TPM_RC_KEY + RC_RSA_Decrypt_keyHandle;
+// The selected key must be an unrestricted decryption key
+if(
+rsaKey->publicArea.objectAttributes.restricted == SET
+|| rsaKey->publicArea.objectAttributes.decrypt == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_RSA_Decrypt_keyHandle;
+//
+//
+//
+//
+
+NOTE: Proper operation of this command requires that the sensitive area
+of the key is loaded. This is assured because authorization is required
+to use the sensitive area of the key. In order to check the authorization,
+the sensitive area has to be loaded, even if authorization is with policy.
+
+// If label is present, make sure that it is a NULL-terminated string
+if(in->label.t.size > 0)
+{
+// Present, so make sure that it is NULL-terminated
+if(in->label.t.buffer[in->label.t.size - 1] != 0)
+return TPM_RC_VALUE + RC_RSA_Decrypt_label;
+label = (char *)in->label.t.buffer;
+}
+// Command Output
+// Select a scheme for decrypt.
+scheme = CryptSelectRSAScheme(in->keyHandle, &in->inScheme);
+if(scheme == NULL)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 99
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+Trusted Platform Module Library
+
+return TPM_RC_SCHEME + RC_RSA_Decrypt_inScheme;
+// Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be
+// returned by CryptDecryptRSA.
+// NOTE: CryptDecryptRSA can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING
+// when the key is not a decryption key but that was checked above.
+out->message.t.size = sizeof(out->message.t.buffer);
+result = CryptDecryptRSA(&out->message.t.size, out->message.t.buffer, rsaKey,
+scheme, in->cipherText.t.size,
+in->cipherText.t.buffer,
+label);
+return result;
+}
+#endif
+
+Page 100
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.4
+
+Part 3: Commands
+
+TPM2_ECDH_KeyGen
+
+16.4.1 General Description
+This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe ≔ [de]G). It uses the private
+ephemeral key and a loaded public key (QS) to compute the shared secret value (P ≔ [hde]QS).
+
+keyHandle shall refer to a loaded ECC key. The sensitive portion of this key need not be loaded.
+The curve parameters of the loaded ECC key are used to generate the ephemeral key.
+NOTE 1
+
+This function is the equivalent of encrypting data to another object’s public key. The seed value is
+used in a KDF to generate a symmetric key and that key is used to encrypt the data. Once the data
+is encrypted and the symmetric key discarded, only the ob ject with the private portion of the
+keyHandle will be able to decrypt it.
+
+The zPoint in the response may be encrypted using parameter encryption.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 101
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.4.2 Command and Response
+Table 47 — TPM2_ECDH_KeyGen Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ECDH_KeyGen
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+Handle of a loaded ECC key public area.
+Auth Index: None
+
+Table 48 — TPM2_ECDH_KeyGen Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+zPoint
+
+results of P ≔ h[de]Qs
+
+TPM2B_ECC_POINT
+
+pubPoint
+
+generated ephemeral public point (Qe)
+
+Page 102
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.4.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ECDH_KeyGen_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_KEY
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+keyHandle does not reference a non-restricted decryption ECC key
+
+TPM_RC
+TPM2_ECDH_KeyGen(
+ECDH_KeyGen_In
+ECDH_KeyGen_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+TPM2B_ECC_PARAMETER
+TPM_RC
+
+*eccKey;
+sensitive;
+result;
+
+// Input Validation
+eccKey = ObjectGet(in->keyHandle);
+// Input key must be a non-restricted, decrypt ECC key
+if(
+eccKey->publicArea.type != TPM_ALG_ECC
+|| eccKey->publicArea.objectAttributes.restricted == SET
+|| eccKey->publicArea.objectAttributes.decrypt != SET
+)
+return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
+// Command Output
+do
+{
+// Create ephemeral ECC key
+CryptNewEccKey(eccKey->publicArea.parameters.eccDetail.curveID,
+&out->pubPoint.t.point, &sensitive);
+out->pubPoint.t.size = TPMS_ECC_POINT_Marshal(&out->pubPoint.t.point,
+NULL, NULL);
+// Compute Z
+result = CryptEccPointMultiply(&out->zPoint.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+&sensitive, &eccKey->publicArea.unique.ecc);
+// The point in the key is not on the curve. Indicate that the key is bad.
+if(result == TPM_RC_ECC_POINT)
+return TPM_RC_KEY + RC_ECDH_KeyGen_keyHandle;
+// The other possible error is TPM_RC_NO_RESULT indicating that the
+// multiplication resulted in the point at infinity, so get a new
+// random key and start over (hardly ever happens).
+}
+while(result != TPM_RC_SUCCESS);
+// Marshal the values to generate the point.
+out->zPoint.t.size = TPMS_ECC_POINT_Marshal(&out->zPoint.t.point, NULL, NULL);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 103
+October 31, 2013
+
+ Part 3: Commands
+
+16.5
+
+Trusted Platform Module Library
+
+TPM2_ECDH_ZGen
+
+16.5.1 General Description
+This command uses the TPM to recover the Z value from a public point (QB) and a private key (ds). It will
+perform the multiplication of the provided inPoint (QB) with the private key (ds) and return the coordinates
+of the resultant point (Z = (xZ , yZ) ≔ [hds]QB; where h is the cofactor of the curve).
+keyHandle shall refer to a loaded, ECC key (TPM_RC_KEY) with the restricted attribute CLEAR and the
+decrypt attribute SET (TPM_RC_ATTRIBUTES).
+The scheme of the key referenced by keyHandle is required to be either TPM_ALG_ECDH or
+TPM_ALG_NULL (TPM_RC_SCHEME).
+inPoint is required to be on the curve of the key referenced by keyHandle (TPM_RC_ECC_POINT).
+The parameters of the key referenced by keyHandle are used to perform the point multiplication.
+
+Page 104
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+16.5.2 Command and Response
+Table 49 — TPM2_ECDH_ZGen Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ECDH_ZGen
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+handle of a loaded ECC key
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_ECC_POINT
+
+inPoint
+
+a public key
+
+Table 50 — TPM2_ECDH_ZGen Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+outPoint
+
+Family “2.0”
+Level 00 Revision 00.99
+
+X and Y coordinates of the product of the multiplication
+
+Z = (xZ , yZ) ≔ [hdS]QB
+
+Published
+Copyright © TCG 2006-2013
+
+Page 105
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ECDH_ZGen_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_KEY
+
+keyHandle does not reference a non-restricted decryption ECC key
+
+TPM_RC_ECC_POINT
+
+invalid argument
+
+TPM_RC_NO_RESULT
+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
+33
+34
+35
+36
+37
+38
+39
+
+Meaning
+
+multiplying inPoint resulted in a point at infinity
+
+TPM_RC
+TPM2_ECDH_ZGen(
+ECDH_ZGen_In
+ECDH_ZGen_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+OBJECT
+
+result;
+*eccKey;
+
+// Input Validation
+eccKey = ObjectGet(in->keyHandle);
+// Input key must be a non-restricted, decrypt ECC key
+if(
+eccKey->publicArea.type != TPM_ALG_ECC
+|| eccKey->publicArea.objectAttributes.restricted == SET
+|| eccKey->publicArea.objectAttributes.decrypt != SET
+)
+return TPM_RC_KEY + RC_ECDH_ZGen_keyHandle;
+// Command Output
+// Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here.
+result = CryptEccPointMultiply(&out->outPoint.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+&eccKey->sensitive.sensitive.ecc,
+&in->inPoint.t.point);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint);
+out->outPoint.t.size = TPMS_ECC_POINT_Marshal(&out->outPoint.t.point,
+NULL, NULL);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 106
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.6
+
+Part 3: Commands
+
+TPM2_ECC_Parameters
+
+16.6.1 General Description
+This command returns the parameters of an ECC curve identified by its TCG-assigned curveID.
+16.6.2 Command and Response
+Table 51 — TPM2_ECC_Parameters Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ECC_Parameters
+
+TPMI_ECC_CURVE
+
+curveID
+
+parameter set selector
+
+Table 52 — TPM2_ECC_Parameters Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMS_ALGORITHM_DETAIL_ECC
+
+parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ECC parameters for the selected curve
+
+Published
+Copyright © TCG 2006-2013
+
+Page 107
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+16.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ECC_Parameters_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_VALUE
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
+Meaning
+Unsupported ECC curve ID
+
+TPM_RC
+TPM2_ECC_Parameters(
+ECC_Parameters_In
+ECC_Parameters_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Get ECC curve parameters
+if(CryptEccGetParameters(in->curveID, &out->parameters))
+return TPM_RC_SUCCESS;
+else
+return TPM_RC_VALUE + RC_ECC_Parameters_curveID;
+}
+#endif
+
+16.7
+16.7.1
+
+TPM2_ZGen_2Phase
+General Description
+
+This command supports two-phase key exchange protocols. The command is used in combination with
+TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key and returns the public
+point of that ephemeral key along with a numeric value that allows the TPM to regenerate the associated
+private key.
+The input parameters for this command are a static public key (inQsU), an ephemeral key (inQeU) from
+party B, and the commitCounter returned by TPM2_EC_Ephemeral(). The TPM uses the counter value to
+regenerate the ephemeral private key (de,V) and the associated public key (Qe,V). keyA provides the static
+ephemeral elements ds,V and Qs,V. This provides the two pairs of ephemeral and static keys that are
+required for the schemes supported by this command.
+The TPM will compute Z or Zs and Ze according to the selected scheme. If the scheme is not a two-phase
+key exchange scheme or if the scheme is not supported, the TPM will return TPM_RC_SCHEME.
+It is an error if inQsB or inQeB are not on the curve of keyA (TPM_RC_ECC_POINT).
+The two-phase key schemes that were assigned an algorithm ID as of the time of the publication of this
+specification are TPM_ALG_ECDH, TPM_ALG_ECMQV, and TPM_ALG_SM2.
+If this command is supported, then support for TPM_ALG_ECDH is required. Support for
+TPM_ALG_ECMQV or TPM_ALG_SM2 is optional.
+NOTE 1
+
+If SM2 is supported and this command is supported, then the implementation is required to support
+the key exchange protocol of SM2, part 3.
+
+For TPM_ALG_ECDH outZ1 will be Zs and outZ2 will Ze as defined in 6.1.1.2 of SP800-56A.
+
+Page 108
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+NOTE 2
+
+Part 3: Commands
+
+A non-restricted decryption key using ECDH may be used in either TPM2_ECDH_ZGen() or
+TPM2_ZGen_2Phase as the computation done with the private part of keyA is the same in both
+cases.
+
+For TPM_ALG_ECMQV or TPM_ALG_SM2 outZ1 will be Z and outZ2 will be an Empty Point.
+NOTE 3
+
+An Empty Point has two Empty Buffers as coordinates meaning the minimum size value for outZ2
+will be four.
+
+If the input scheme is TPM_ALG_ECDH, then outZ1 will be Zs and outZ2 will be Ze. For schemes like
+MQV (including SM2), outZ1 will contain the computed value and outZ2 will be an Empty Point.
+NOTE
+
+The Z values returned by the TPM are a full point and not ju st an x-coordinate.
+
+If a computation of either Z produces the point at infinity, then the corresponding Z value will be an Empty
+Point.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 109
+October 31, 2013
+
+ Part 3: Commands
+
+16.7.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 53 — TPM2_ZGen_2Phase Command
+
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+Description
+
+TPM_CC_ZGen_2Phase
+handle of an unrestricted decryption key ECC
+The private key referenced by this handle is used as dS,A
+
+TPMI_DH_OBJECT
+
+@keyA
+
+TPM2B_ECC_POINT
+
+inQsB
+
+other party’s static public key (Qs,B = (Xs,B, Ys,B))
+
+TPM2B_ECC_POINT
+
+inQeB
+
+other party's ephemeral public key (Qe,B = (Xe,B, Ye,B))
+
+TPMI_ECC_KEY_EXCHANGE
+
+inScheme
+
+the key exchange scheme
+
+UINT16
+
+counter
+
+value returned by TPM2_EC_Ephemeral()
+
+Auth Index: 1
+Auth Role: USER
+
+Table 54 — TPM2_ZGen_2Phase Response
+Type
+
+Name
+
+TPM_ST
+
+tag
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+outZ1
+
+X and Y coordinates of the computed value (scheme
+dependent)
+
+TPM2B_ECC_POINT
+
+outZ2
+
+X and Y coordinates of the second computed value
+(scheme dependent)
+
+Page 110
+October 31, 2013
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+16.7.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "ZGen_2Phase_fp.h"
+#if defined TPM_ALG_ECC && (CC_ZGen_2Phase == YES)
+
+This command uses the TPM to recover one or two Z values in a two phase key exchange protocol
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by keyA is restricted or not a decrypt key
+
+TPM_RC_ECC_POINT
+
+inQsB or inQeB is not on the curve of the key reference by keyA
+
+TPM_RC_KEY
+
+key referenced by keyA is not an ECC key
+
+TPM_RC_SCHEME
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
+Meaning
+
+the scheme of the key referenced by keyA is not TPM_ALG_NULL,
+TPM_ALG_ECDH, TPM_ALG_ECMQV or TPM_ALG_SM2
+
+TPM_RC
+TPM2_ZGen_2Phase(
+ZGen_2Phase_In
+ZGen_2Phase_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+OBJECT
+TPM2B_ECC_PARAMETER
+TPM_ALG_ID
+
+result;
+*eccKey;
+r;
+scheme;
+
+// Input Validation
+eccKey = ObjectGet(in->keyA);
+// keyA must be an ECC key
+if(eccKey->publicArea.type != TPM_ALG_ECC)
+return TPM_RC_KEY + RC_ZGen_2Phase_keyA;
+// keyA must not be restricted and must be a decrypt key
+if(
+eccKey->publicArea.objectAttributes.restricted == SET
+|| eccKey->publicArea.objectAttributes.decrypt != SET
+)
+return TPM_RC_ATTRIBUTES + RC_ZGen_2Phase_keyA;
+// if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise
+// the input scheme must be the same as the scheme of keyA
+scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme;
+if(scheme != TPM_ALG_NULL)
+{
+if(scheme != in->inScheme)
+return TPM_RC_SCHEME + RC_ZGen_2Phase_inScheme;
+}
+else
+scheme = in->inScheme;
+if(scheme == TPM_ALG_NULL)
+return TPM_RC_SCHEME + RC_ZGen_2Phase_inScheme;
+// Input points must be on the curve of keyA
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+&in->inQsB.t.point))
+return TPM_RC_ECC_POINT + RC_ZGen_2Phase_inQsB;
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 111
+October 31, 2013
+
+ Part 3: Commands
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
+Trusted Platform Module Library
+
+&in->inQeB.t.point))
+return TPM_RC_ECC_POINT + RC_ZGen_2Phase_inQeB;
+if(!CryptGenerateR(&r, &in->counter,
+eccKey->publicArea.parameters.eccDetail.curveID,
+NULL))
+return TPM_RC_VALUE + RC_ZGen_2Phase_counter;
+// Command Output
+result = CryptEcc2PhaseKeyExchange(&out->outZ1.t.point,
+&out->outZ2.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+scheme,
+&eccKey->sensitive.sensitive.ecc,
+&r,
+&in->inQsB.t.point,
+&in->inQeB.t.point);
+if(result != TPM_RC_SUCCESS)
+return result;
+CryptEndCommit(in->counter);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 112
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+17
+17.1
+
+Part 3: Commands
+
+Symmetric Primitives
+Introduction
+
+The commands in this clause provide low-level primitives for access to the symmetric algorithms
+implemented in the TPM that operate on blocks of data. These include symmetric encryption and
+decryption as well as hash and HMAC. All of the commands in this group are stateless. That is, they have
+no persistent state that is retained in the TPM when the command is complete.
+For hashing, HMAC, and Events that require large blocks of data with retained state, the sequence
+commands are provided (see clause 1).
+Some of the symmetric encryption/decryption modes use an IV. When an IV is used, it may be an
+initiation value or a chained value from a previous stage. The chaining for each mode is:
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 113
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+Table 55 — Symmetric Chaining Process
+
+Mode
+
+Chaining process
+
+TPM_ALG_CTR
+
+The TPM will increment the entire IV provided by the caller. The last encrypted value will be
+returned to the caller as ivOut. This can be the input value to the next encrypted buffer.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+EXAMPLE 1 AES requires that ivIn be 128 bits (16 octets).
+
+ivOut will be the size of a cipher block and not the size of the last encrypted block.
+NOTE
+
+ivOut will be the value of the counter after the last block is encrypted.
+
+EXAMPLE 2 If ivIn were 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0016 and four data blocks
+were encrypted, ivOut will have a value of
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0416.
+
+All the bits of the IV are incremented as if it were an unsigned integer.
+TPM_ALG_OFB
+
+In Output Feedback (OFB), the output of the pseudo-random function (the block encryption
+algorithm) is XORed with a plaintext block to produce a ciphertext block. ivOut will be the
+value that was XORed with the last plaintext block. That value can be used as the ivIn for a
+next buffer.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+ivOut will be the size of a cipher block and not the size of the last encrypted block.
+
+TPM_ALG_CBC
+
+For Cipher Block Chaining (CBC), a block of ciphertext is XORed with the next plaintext
+block and that block is encrypted. The encrypted block is then input to the encryption of the
+next block. The last ciphertext block then is used as an IV for the next buffer.
+Even though the last ciphertext block is evident in the encrypted data, it is also returned in
+ivOut.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+inData is required to be an even multiple of the block encrypted by the selected algorithm
+and key combination. If the size of inData is not correct, the TPM shall return
+TPM_RC_SIZE.
+
+TPM_ALG_CFB
+
+Similar to CBC in that the last ciphertext block is an input to the encryption of the next block.
+ivOut will be the value that was XORed with the last plaintext block. That value can be used
+as the ivIn for a next buffer.
+ivIn is required to be the size of a block encrypted by the selected algorithm and key
+combination. If the size of ivIn is not correct, the TPM shall return TPM_RC_SIZE.
+ivOut will be the size of a cipher block and not the size of the last encrypted block.
+
+TPM_ALG_ECB
+
+Electronic Codebook (ECB) has no chaining. Each block of plaintext is encrypted using the
+key. ECB does not support chaining and ivIn shall be the Empty Buffer. ivOut will be the
+Empty Buffer.
+inData is required to be an even multiple of the block encrypted by the selected algorithm
+and key combination. If the size of inData is not correct, the TPM shall return
+TPM_RC_SIZE.
+
+Page 114
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+17.2
+
+Part 3: Commands
+
+TPM2_EncryptDecrypt
+
+17.2.1 General Description
+This command performs symmetric encryption or decryption.
+keyHandle shall reference a symmetric cipher object (TPM_RC_KEY).
+For a restricted key, mode shall be either the same as the mode of the key, or TPM_ALG_NULL
+(TPM_RC_VALUE). For an unrestricted key, mode may be the same or different from the mode of the key
+but both shall not be TPM_ALG_NULL (TPM_RC_VALUE).
+If the TPM allows this command to be canceled before completion, then the TPM may produce
+incremental results and return TPM_RC_SUCCESS rather than TPM_RC_CANCEL. In such case,
+outData may be less than inData.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 115
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+17.2.2 Command and Response
+Table 56 — TPM2_EncryptDecrypt Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EncryptDecrypt
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+the symmetric key used for the operation
+Auth Index: 1
+Auth Role: USER
+
+TPMI_YES_NO
+
+decrypt
+
+if YES, then the operation is decryption; if NO, the
+operation is encryption
+
+TPMI_ALG_SYM_MODE+
+
+mode
+
+symmetric mode
+For a restricted key, this field shall match the default
+mode of the key or be TPM_ALG_NULL.
+
+TPM2B_IV
+
+ivIn
+
+an initial value as required by the algorithm
+
+TPM2B_MAX_BUFFER
+
+inData
+
+the data to be encrypted/decrypted
+
+Table 57 — TPM2_EncryptDecrypt Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_BUFFER
+
+outData
+
+encrypted output
+
+TPM2B_IV
+
+ivOut
+
+chaining value to use for IV in next round
+
+Page 116
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+17.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "EncryptDecrypt_fp.h"
+Error Returns
+TPM_RC_KEY
+
+is not a symmetric decryption key with both public and private
+portions loaded
+
+TPM_RC_SIZE
+
+IvIn size is incompatible with the block cipher mode; or inData size is
+not an even multiple of the block size for CBC or ECB mode
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+
+Meaning
+
+keyHandle is restricted and the argument mode does not match the
+key's mode
+
+TPM_RC
+TPM2_EncryptDecrypt(
+EncryptDecrypt_In
+EncryptDecrypt_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+UINT16
+UINT16
+BYTE
+TPM_ALG_ID
+
+*symKey;
+keySize;
+blockSize;
+*key;
+alg;
+
+// Input Validation
+symKey = ObjectGet(in->keyHandle);
+// The input key should be a symmetric decrypt key.
+if(
+symKey->publicArea.type != TPM_ALG_SYMCIPHER
+|| symKey->attributes.publicOnly == SET)
+return TPM_RC_KEY + RC_EncryptDecrypt_keyHandle;
+// If the input mode is TPM_ALG_NULL, use the key's mode
+if( in->mode == TPM_ALG_NULL)
+in->mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;
+// If the key is restricted, the input sym mode should match the key's sym
+// mode
+if(
+symKey->publicArea.objectAttributes.restricted == SET
+&& symKey->publicArea.parameters.symDetail.sym.mode.sym != in->mode)
+return TPM_RC_VALUE + RC_EncryptDecrypt_mode;
+// If the mode is null, then we have a problem.
+// Note: Construction of a TPMT_SYM_DEF does not allow the 'mode' to be
+// TPM_ALG_NULL so setting in->mode to the mode of the key should have
+// produced a valid mode. However, this is suspenders.
+if(in->mode == TPM_ALG_NULL)
+return TPM_RC_VALUE + RC_EncryptDecrypt_mode;
+// The input iv for ECB mode should be null. All the other modes should
+// have an iv size same as encryption block size
+keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym;
+alg = symKey->publicArea.parameters.symDetail.sym.algorithm;
+blockSize = CryptGetSymmetricBlockSize(alg, keySize);
+if(
+(in->mode == TPM_ALG_ECB && in->ivIn.t.size != 0)
+|| (in->mode != TPM_ALG_ECB && in->ivIn.t.size != blockSize))
+return TPM_RC_SIZE + RC_EncryptDecrypt_ivIn;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 117
+October 31, 2013
+
+ Part 3: Commands
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+
+Trusted Platform Module Library
+
+// The input data size of CBC mode or ECB mode must be an even multiple of
+// the symmetric algorithm's block size
+if(
+(in->mode == TPM_ALG_CBC || in->mode == TPM_ALG_ECB)
+&& (in->inData.t.size % blockSize) != 0)
+return TPM_RC_SIZE + RC_EncryptDecrypt_inData;
+// Copy IV
+// Note: This is copied here so that the calls to the encrypt/decrypt functions
+// will modify the output buffer, not the input buffer
+out->ivOut = in->ivIn;
+// Command Output
+key = symKey->sensitive.sensitive.sym.t.buffer;
+// For symmetric encryption, the cipher data size is the same as plain data
+// size.
+out->outData.t.size = in->inData.t.size;
+if(in->decrypt == YES)
+{
+// Decrypt data to output
+CryptSymmetricDecrypt(out->outData.t.buffer,
+alg,
+keySize, in->mode, key,
+&(out->ivOut),
+in->inData.t.size,
+in->inData.t.buffer);
+}
+else
+{
+// Encrypt data to output
+CryptSymmetricEncrypt(out->outData.t.buffer,
+alg,
+keySize,
+in->mode, key,
+&(out->ivOut),
+in->inData.t.size,
+in->inData.t.buffer);
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 118
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+17.3
+
+Part 3: Commands
+
+TPM2_Hash
+
+17.3.1 General Description
+This command performs a hash operation on a data buffer and returns the results.
+NOTE
+
+If the data buffer to be hashed is larger than will fit into the TPM’s input buffer, then the sequence
+hash commands will need to be used.
+
+If the results of the hash will be used in a signing operation that uses a restricted signing key, then the
+ticket returned by this command can indicate that the hash is safe to sign.
+If the digest is not safe to sign, then the TPM will return a TPMT_TK_HASHCHECK with the hierarchy set
+to TPM_RH_NULL and digest set to the Empty Buffer.
+If hierarchy is TPM_RH_NULL, then digest in the ticket will be the Empty Buffer.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 119
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+17.3.2 Command and Response
+Table 58 — TPM2_Hash Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+Shall have at least one session
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Hash
+
+TPM2B_MAX_BUFFER
+
+data
+
+data to be hashed
+
+TPMI_ALG_HASH
+
+hashAlg
+
+algorithm for the hash being computed – shall not be
+TPM_ALG_NULL
+
+TPMI_RH_HIERARCHY+
+
+hierarchy
+
+hierarchy to use for the ticket (TPM_RH_NULL allowed)
+
+Table 59 — TPM2_Hash Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+outHash
+
+results
+
+TPMT_TK_HASHCHECK
+
+validation
+
+ticket indicating that the sequence of octets used to
+compute outDigest did not start with
+TPM_GENERATED_VALUE
+will be a NULL ticket if the digest may not be signed
+with a restricted key
+
+Page 120
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+17.3.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+
+#include "InternalRoutines.h"
+#include "Hash_fp.h"
+
+TPM_RC
+TPM2_Hash(
+Hash_In
+Hash_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+HASH_STATE
+
+hashState;
+
+// Command Output
+// Output hash
+// Start hash stack
+out->outHash.t.size = CryptStartHash(in->hashAlg, &hashState);
+// Adding hash data
+CryptUpdateDigest2B(&hashState, &in->data.b);
+// Complete hash
+CryptCompleteHash2B(&hashState, &out->outHash.b);
+// Output ticket
+out->validation.tag = TPM_ST_HASHCHECK;
+out->validation.hierarchy = in->hierarchy;
+if(in->hierarchy == TPM_RH_NULL)
+{
+// Ticket is not required
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else if( in->data.t.size >= sizeof(TPM_GENERATED)
+&& !TicketIsSafe(&in->data.b))
+{
+// Ticket is not safe
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else
+{
+// Compute ticket
+TicketComputeHashCheck(in->hierarchy, &out->outHash, &out->validation);
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 121
+October 31, 2013
+
+ Part 3: Commands
+
+17.4
+
+Trusted Platform Module Library
+
+TPM2_HMAC
+
+17.4.1 General Description
+This command performs an HMAC on the supplied data using the indicated hash algorithm.
+The caller shall provide proper authorization for use of handle.
+If the sign attribute is not SET in the key referenced by handle then the TPM shall return
+TPM_RC_ATTRIBUTES. If the key type is not TPM_ALG_KEYEDHASH then the TPM shall return
+TPM_RC_TYPE.
+If handle references a restricted key, then the hash algorithm specified in the key's scheme is used as the
+hash algorithm for the HMAC and the TPM shall return TPM_RC_VALUE if hashAlg is not
+TPM_ALG_NULL or the same algorithm as selected in the key's scheme.
+NOTE 1
+A restricted key may only have one of sign or decrypt SET and the default scheme may not
+be TPM_ALG_NULL. These restrictions are enforced by TPM2_Create() and TPM2_CreatePrimary(),
+If the key referenced by handle is not restricted, then the TPM will use hashAlg for the HMAC. However, if
+hashAlg is TPM_ALG_NULL the TPM will use the default scheme of the key.
+If both hashAlg and the key default are TPM_ALG_NULL, the TPM shall return TPM_RC_VALUE.
+NOTE
+
+A key may only have both sign and decrypt SET if the key is unrestricted. When bo th sign and
+decrypt are set, there is no default scheme for the key and the hash algorithm must be specified .
+
+Page 122
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+17.4.2 Command and Response
+Table 60 — TPM2_HMAC Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HMAC
+
+TPMI_DH_OBJECT
+
+@handle
+
+handle for the symmetric signing key providing the
+HMAC key
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+HMAC data
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+algorithm to use for HMAC
+
+Table 61 — TPM2_HMAC Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+outHMAC
+
+Family “2.0”
+Level 00 Revision 00.99
+
+the returned HMAC in a sized buffer
+
+Published
+Copyright © TCG 2006-2013
+
+Page 123
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+17.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HMAC_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by handle is not a signing key
+
+TPM_RC_TYPE
+
+key referenced by handle is not an HMAC key
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+hashAlg specified when the key is restricted is neither
+TPM_ALG_NULL not equal to that of the key scheme; or both
+hashAlg and the key scheme's algorithm are TPM_ALG_NULL
+
+TPM_RC
+TPM2_HMAC(
+HMAC_In
+HMAC_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+HMAC_STATE
+OBJECT
+TPMI_ALG_HASH
+TPMT_PUBLIC
+
+hmacState;
+*hmacObject;
+hashAlg;
+*publicArea;
+
+)
+{
+
+// Input Validation
+// Get HMAC key object and public area pointers
+hmacObject = ObjectGet(in->handle);
+publicArea = &hmacObject->publicArea;
+// Make sure that the key is an HMAC signing key
+if(publicArea->type != TPM_ALG_KEYEDHASH)
+return TPM_RC_TYPE + RC_HMAC_handle;
+if(publicArea->objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_HMAC_handle;
+// Assume that the key default scheme is used
+hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
+// if the key is restricted, then need to use the scheme of the key and the
+// input algorithm must be TPM_ALG_NULL or the same as the key scheme
+if(publicArea->objectAttributes.restricted == SET)
+{
+if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
+hashAlg = TPM_ALG_NULL;
+}
+else
+{
+// for a non-restricted key, use hashAlg if it is provided;
+if(in->hashAlg != TPM_ALG_NULL)
+hashAlg = in->hashAlg;
+}
+// if the hashAlg is TPM_ALG_NULL, then the input hashAlg is not compatible
+// with the key scheme or type
+if(hashAlg == TPM_ALG_NULL)
+return TPM_RC_VALUE + RC_HMAC_hashAlg;
+// Command Output
+
+Page 124
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+Part 3: Commands
+
+// Start HMAC stack
+out->outHMAC.t.size = CryptStartHMAC2B(hashAlg,
+&hmacObject->sensitive.sensitive.bits.b,
+&hmacState);
+// Adding HMAC data
+CryptUpdateDigest2B(&hmacState, &in->buffer.b);
+// Complete HMAC
+CryptCompleteHMAC2B(&hmacState, &out->outHMAC.b);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 125
+October 31, 2013
+
+ Part 3: Commands
+
+18
+
+Trusted Platform Module Library
+
+Random Number Generator
+
+18.1
+
+TPM2_GetRandom
+
+18.1.1 General Description
+This command returns the next bytesRequested octets from the random number generator (RNG).
+NOTE 1
+
+It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG
+octets such that the frequency of bytesRequested being more than the number of octets available is
+an infrequent occurrence.
+
+If bytesRequested is more than will fit into a TPM2B_DIGEST on the TPM, no error is returned but the
+TPM will only return as much data as will fit into a TPM2B_DIGEST buffer for the TPM.
+NOTE 2
+
+TPM2B_DIGEST is large enough to hold the largest digest that may be produced by the TPM.
+Because that digest size changes according to the implemented hashes, the maximum amount of
+data returned by this command is TPM implementation-dependent.
+
+Page 126
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+18.1.2 Command and Response
+Table 62 — TPM2_GetRandom Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetRandom
+
+UINT16
+
+bytesRequested
+
+number of octets to return
+
+Table 63 — TPM2_GetRandom Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+randomBytes
+
+Family “2.0”
+Level 00 Revision 00.99
+
+the random octets
+
+Published
+Copyright © TCG 2006-2013
+
+Page 127
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+18.1.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
+#include "InternalRoutines.h"
+#include "GetRandom_fp.h"
+
+TPM_RC
+TPM2_GetRandom(
+GetRandom_In
+GetRandom_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// if the requested bytes exceed the output buffer size, generates the
+// maximum bytes that the output buffer allows
+if(in->bytesRequested > sizeof(TPMU_HA))
+out->randomBytes.t.size = sizeof(TPMU_HA);
+else
+out->randomBytes.t.size = in->bytesRequested;
+CryptGenerateRandom(out->randomBytes.t.size, out->randomBytes.t.buffer);
+return TPM_RC_SUCCESS;
+}
+
+Page 128
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+18.2
+
+Part 3: Commands
+
+TPM2_StirRandom
+
+18.2.1 General Description
+This command is used to add "additional information" to the RNG state.
+NOTE
+
+The "additional information" is as defined in SP800 -90A.
+
+The inData parameter may not be larger than 128 octets.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 129
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+18.2.2 Command and Response
+Table 64 — TPM2_StirRandom Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_StirRandom {NV}
+
+TPM2B_SENSITIVE_DATA
+
+inData
+
+additional information
+
+Table 65 — TPM2_StirRandom Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 130
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+18.2.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+#include "InternalRoutines.h"
+#include "StirRandom_fp.h"
+
+TPM_RC
+TPM2_StirRandom(
+StirRandom_In
+*in
+// IN: input parameter list
+)
+{
+// Internal Data Update
+CryptStirRandom(in->inData.t.size, in->inData.t.buffer);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 131
+October 31, 2013
+
+ Part 3: Commands
+
+19
+
+Trusted Platform Module Library
+
+Hash/HMAC/Event Sequences
+
+19.1
+
+Introduction
+
+All of the commands in this group are to support sequences for which an intermediate state must be
+maintained. For a description of sequences, see “Hash, HMAC, and Event Sequences” in Part 1.
+19.2
+
+TPM2_HMAC_Start
+
+19.2.1 General Description
+This command starts an HMAC sequence. The TPM will create and initialize an HMAC sequence
+structure, assign a handle to the sequence, and set the authValue of the sequence object to the value in
+auth.
+NOTE 1
+
+The structure of a sequence object is vendor -dependent.
+
+The caller shall provide proper authorization for use of handle.
+If the sign attribute is not SET in the key referenced by handle then the TPM shall return
+TPM_RC_ATTRIBUTES. If the key type is not TPM_ALG_KEYEDHASH then the TPM shall return
+TPM_RC_TYPE.
+If handle references a restricted key, then the hash algorithm specified in the key's scheme is used as the
+hash algorithm for the HMAC and the TPM shall return TPM_RC_VALUE if hashAlg is not
+TPM_ALG_NULL or the same algorithm in the key's scheme.
+If the key referenced by handle is not restricted, then the TPM will use hashAlg for the HMAC; unless
+hashAlg is TPM_ALG_NULL in which case it will use the default scheme of the key.
+Table 66 — Hash Selection Matrix
+handle→restricted
+(key's restricted
+attribute)
+
+handle→scheme
+(hash algorithm
+from key's scheme)
+
+CLEAR (unrestricted)
+
+TPM_ALG_NULL
+
+CLEAR
+
+don’t care
+
+CLEAR
+
+valid hash
+
+hash used
+
+TPM_ALG_NULL
+
+error
+
+valid hash
+
+(1)
+
+hashAlg
+
+hashAlg
+
+(2)
+
+(TPM_RC_SCHEME)
+
+TPM_ALG_NULL
+
+handle→scheme
+
+same as handle→scheme
+
+handle→scheme
+
+(3)
+
+SET
+
+handle→scheme
+
+(3)
+
+SET (restricted)
+
+TPM_ALG_NULL
+
+(3)
+
+not same as
+handle→scheme
+
+error
+
+valid hash
+valid hash
+
+SET
+
+valid hash
+
+(4)
+
+(TPM_RC_SCHEME)
+
+NOTES:
+1)
+
+The scheme for the handle may only be TPM_ALG_NULL if both sign and decrypt are SET.
+
+2)
+
+A hash algorithm is required for the HMAC.
+
+3)
+
+A restricted key is required to have a scheme with a valid hash algorithm. A restricted key may not have both sign and
+decrypt SET.
+
+4)
+
+The scheme for a restricted key cannot be overridden.
+
+Page 132
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.2.2 Command and Response
+Table 67 — TPM2_HMAC_Start Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HMAC_Start
+
+TPMI_DH_OBJECT
+
+@handle
+
+handle of an HMAC key
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_AUTH
+
+auth
+
+authorization value for subsequent use of the sequence
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+the hash algorithm to use for the HMAC
+
+Table 68 — TPM2_HMAC_Start Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_DH_OBJECT
+
+sequenceHandle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+a handle to reference the sequence
+
+Published
+Copyright © TCG 2006-2013
+
+Page 133
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HMAC_Start_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by handle is not a signing key
+
+TPM_RC_OBJECT_MEMORY
+
+no space to create an internal object
+
+TPM_RC_TYPE
+
+key referenced by handle is not an HMAC key
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+
+Meaning
+
+hashAlg specified when the key is restricted is neither
+TPM_ALG_NULL not equal to that of the key scheme; or both
+hashAlg and the key scheme's algorithm are TPM_ALG_NULL
+
+TPM_RC
+TPM2_HMAC_Start(
+HMAC_Start_In
+HMAC_Start_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+TPMT_PUBLIC
+TPM_ALG_ID
+
+*hmacObject;
+*publicArea;
+hashAlg;
+
+// Input Validation
+// Get HMAC key object and public area pointers
+hmacObject = ObjectGet(in->handle);
+publicArea = &hmacObject->publicArea;
+// Make sure that the key is an HMAC signing key
+if(publicArea->type != TPM_ALG_KEYEDHASH)
+return TPM_RC_TYPE + RC_HMAC_Start_handle;
+if(publicArea->objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_HMAC_Start_handle;
+// Assume that the key default scheme is used
+hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
+// if the key is restricted, then need to use the scheme of the key and the
+// input algorithm must be TPM_ALG_NULL or the same as the key scheme
+if(publicArea->objectAttributes.restricted == SET)
+{
+if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
+hashAlg = TPM_ALG_NULL;
+}
+else
+{
+// for a non-restricted key, use hashAlg if it is provided;
+if(in->hashAlg != TPM_ALG_NULL)
+hashAlg = in->hashAlg;
+}
+// if the algorithm selection ended up with TPM_ALG_NULL, then either the
+// schemes are not compatible or no hash was provided and both conditions
+// are errors.
+if(hashAlg == TPM_ALG_NULL)
+return TPM_RC_VALUE + RC_HMAC_Start_hashAlg;
+// Internal Data Update
+
+Page 134
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+48
+49
+50
+51
+52
+53
+54
+55
+
+Part 3: Commands
+
+// Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
+// returned at this point
+return ObjectCreateHMACSequence(hashAlg,
+in->handle,
+&in->auth,
+&out->sequenceHandle);
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 135
+October 31, 2013
+
+ Part 3: Commands
+
+19.3
+
+Trusted Platform Module Library
+
+TPM2_HashSequenceStart
+
+19.3.1 General Description
+This command starts a hash or an Event sequence. If hashAlg is an implemented hash, then a hash
+sequence is started. If hashAlg is TPM_ALG_NULL, then an Event sequence is started. If hashAlg is
+neither an implemented algorithm nor TPM_ALG_NULL, then the TPM shall return TPM_RC_HASH.
+Depending on hashAlg, the TPM will create and initialize a hash sequence structure or an Event
+sequence structure. Additionally, it will assign a handle to the sequence and set the authValue of the
+sequence to the value in auth. A sequence structure for an Event (hashAlg = TPM_ALG_NULL) contains
+a hash context for each of the PCR banks implemented on the TPM.
+
+Page 136
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.3.2 Command and Response
+Table 69 — TPM2_HashSequenceStart Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HashSequenceStart
+
+TPM2B_AUTH
+
+auth
+
+authorization value for subsequent use of the sequence
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+the hash algorithm to use for the hash sequence
+An Event sequence starts if this is TPM_ALG_NULL.
+
+Table 70 — TPM2_HashSequenceStart Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_DH_OBJECT
+
+sequenceHandle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+a handle to reference the sequence
+
+Published
+Copyright © TCG 2006-2013
+
+Page 137
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HashSequenceStart_fp.h"
+Error Returns
+TPM_RC_OBJECT_MEMORY
+
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
+Meaning
+no space to create an internal object
+
+TPM_RC
+TPM2_HashSequenceStart(
+HashSequenceStart_In
+HashSequenceStart_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Internal Data Update
+if(in->hashAlg == TPM_ALG_NULL)
+// Start a event sequence. A TPM_RC_OBJECT_MEMORY error may be
+// returned at this point
+return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle);
+// Start a hash sequence. A TPM_RC_OBJECT_MEMORY error may be
+// returned at this point
+return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle);
+}
+
+Page 138
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+19.4
+
+Part 3: Commands
+
+TPM2_SequenceUpdate
+
+19.4.1 General Description
+This command is used to add data to a hash or HMAC sequence. The amount of data in buffer may be
+any size up to the limits of the TPM.
+NOTE
+
+In all TPM, a buffer size of 1,024 octets is allowed.
+
+Proper authorization for the sequence object associated with sequenceHandle is required. If an
+authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
+associated with sequenceHandle will be the Empty Buffer.
+If the command does not return TPM_RC_SUCCESS, the state of the sequence is unmodified.
+If the sequence is intended to produce a digest that will be signed by a restricted signing key, then the
+first block of data shall contain sizeof(TPM_GENERATED) octets and the first octets shall not be
+TPM_GENERATED_VALUE.
+NOTE
+
+This requirement allows the TPM to validate that the first block is safe to sign without having to
+accumulate octets over multiple calls.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 139
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.4.2 Command and Response
+Table 71 — TPM2_SequenceUpdate Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SequenceUpdate
+
+TPMI_DH_OBJECT
+
+@sequenceHandle
+
+handle for the sequence object
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+data to be added to hash
+
+Table 72 — TPM2_SequenceUpdate Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 140
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "SequenceUpdate_fp.h"
+Error Returns
+TPM_RC_MODE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+sequenceHandle does not reference a hash or HMAC sequence
+object
+
+TPM_RC
+TPM2_SequenceUpdate(
+SequenceUpdate_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+OBJECT
+
+*object;
+
+// Input Validation
+// Get sequence object pointer
+object = ObjectGet(in->sequenceHandle);
+// Check that referenced object is a sequence object.
+if(!ObjectIsSequence(object))
+return TPM_RC_MODE + RC_SequenceUpdate_sequenceHandle;
+// Internal Data Update
+if(object->attributes.eventSeq == SET)
+{
+// Update event sequence object
+UINT32
+i;
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+for(i = 0; i < HASH_COUNT; i++)
+{
+// Update sequence object
+CryptUpdateDigest2B(&hashObject->state.hashState[i], &in->buffer.b);
+}
+}
+else
+{
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+// Update hash/HMAC sequence object
+if(hashObject->attributes.hashSeq == SET)
+{
+// Is this the first block of the sequence
+if(hashObject->attributes.firstBlock == CLEAR)
+{
+// If so, indicate that first block was received
+hashObject->attributes.firstBlock = SET;
+// Check the first block to see if the first block can contain
+// the TPM_GENERATED_VALUE. If it does, it is not safe for
+// a ticket.
+if(TicketIsSafe(&in->buffer.b))
+hashObject->attributes.ticketSafe = SET;
+}
+// Update sequence object hash/HMAC stack
+CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 141
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+
+Trusted Platform Module Library
+
+}
+else if(object->attributes.hmacSeq == SET)
+{
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+// Update sequence object hash/HMAC stack
+CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b);
+}
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 142
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+19.5
+
+Part 3: Commands
+
+TPM2_SequenceComplete
+
+19.5.1 General Description
+This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
+NOTE 1
+
+This command is not used to complete an Event sequence. TPM2_EventSequenceComplete() is
+used for that purpose.
+
+For a hash sequence, if the results of the hash will be used in a signing operation that uses a restricted
+signing key, then the ticket returned by this command can indicate that the hash is safe to sign.
+If the digest is not safe to sign, then validation will be a TPMT_TK_HASHCHECK with the hierarchy set to
+TPM_RH_NULL and digest set to the Empty Buffer.
+NOTE 2
+
+Regardless of the contents of the first octets of the hashed message, if the first buffer sent to the
+TPM had fewer than sizeof(TPM_GENERATED) octets, then the TPM will operate as if digest is not
+safe to sign.
+
+If sequenceHandle references an Event sequence, then the TPM shall return TPM_RC_MODE.
+Proper authorization for the sequence object associated with sequenceHandle is required. If an
+authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
+associated with sequenceHandle will be the Empty Buffer.
+If this command completes successfully, the sequenceHandle object will be flushed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 143
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.5.2 Command and Response
+Table 73 — TPM2_SequenceComplete Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SequenceComplete {F}
+
+TPMI_DH_OBJECT
+
+@sequenceHandle
+
+authorization for the sequence
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+data to be added to the hash/HMAC
+
+TPMI_RH_HIERARCHY+
+
+hierarchy
+
+hierarchy of the ticket for a hash
+
+Table 74 — TPM2_SequenceComplete Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+result
+
+the returned HMAC or digest in a sized buffer
+
+TPMT_TK_HASHCHECK
+
+validation
+
+ticket indicating that the sequence of octets used to
+compute outDigest did not start with
+TPM_GENERATED_VALUE
+This is a NULL Ticket when the session is HMAC.
+
+Page 144
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "SequenceComplete_fp.h"
+#include <Platform.h>
+Error Returns
+TPM_RC_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+sequenceHandle does not reference a hash or HMAC sequence
+object
+
+TPM_RC
+TPM2_SequenceComplete(
+SequenceComplete_In
+SequenceComplete_Out
+
+*in,
+*out
+
+OBJECT
+
+// IN: input parameter list
+// OUT: output parameter list
+
+*object;
+
+)
+{
+// Input validation
+// Get hash object pointer
+object = ObjectGet(in->sequenceHandle);
+// input handle must be a hash or HMAC sequence object.
+if(
+object->attributes.hashSeq == CLEAR
+&& object->attributes.hmacSeq == CLEAR)
+return TPM_RC_MODE + RC_SequenceComplete_sequenceHandle;
+// Command Output
+if(object->attributes.hashSeq == SET)
+// sequence object for hash
+{
+// Update last piece of data
+HASH_OBJECT
+*hashObject = (HASH_OBJECT *)object;
+CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b);
+// Complete hash
+out->result.t.size
+= CryptGetHashDigestSize(
+CryptGetContextAlg(&hashObject->state.hashState[0]));
+CryptCompleteHash2B(&hashObject->state.hashState[0], &out->result.b);
+// Check if the first block of the sequence has been received
+if(hashObject->attributes.firstBlock == CLEAR)
+{
+// If not, then this is the first block so see if it is 'safe'
+// to sign.
+if(TicketIsSafe(&in->buffer.b))
+hashObject->attributes.ticketSafe = SET;
+}
+// Output ticket
+out->validation.tag = TPM_ST_HASHCHECK;
+out->validation.hierarchy = in->hierarchy;
+if(in->hierarchy == TPM_RH_NULL)
+{
+// Ticket is not required
+out->validation.digest.t.size = 0;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 145
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+
+Trusted Platform Module Library
+
+}
+else if(object->attributes.ticketSafe == CLEAR)
+{
+// Ticket is not safe to generate
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else
+{
+// Compute ticket
+TicketComputeHashCheck(out->validation.hierarchy,
+&out->result, &out->validation);
+}
+}
+else
+{
+HASH_OBJECT
+
+*hashObject = (HASH_OBJECT *)object;
+
+//
+Update last piece of data
+CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b);
+// Complete hash/HMAC
+out->result.t.size =
+CryptGetHashDigestSize(
+CryptGetContextAlg(&hashObject->state.hmacState.hashState));
+CryptCompleteHMAC2B(&(hashObject->state.hmacState), &out->result.b);
+// No ticket is generated for HMAC sequence
+out->validation.tag = TPM_ST_HASHCHECK;
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+// Internal Data Update
+// mark sequence object as evict so it will be flushed on the way out
+object->attributes.evict = SET;
+return TPM_RC_SUCCESS;
+}
+
+Page 146
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+19.6
+
+Part 3: Commands
+
+TPM2_EventSequenceComplete
+
+19.6.1 General Description
+This command adds the last part of data, if any, to an Event sequence and returns the result in a digest
+list. If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in
+the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each
+bank extended with the associated digest value.
+If sequenceHandle references a hash or HMAC sequence, the TPM shall return TPM_RC_MODE.
+Proper authorization for the sequence object associated with sequenceHandle is required. If an
+authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
+associated with sequenceHandle will be the Empty Buffer.
+If this command completes successfully, the sequenceHandle object will be flushed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 147
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+19.6.2 Command and Response
+Table 75 — TPM2_EventSequenceComplete Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EventSequenceComplete {NV F}
+
+TPMI_DH_PCR+
+
+@pcrHandle
+
+PCR to be extended with the Event data
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+@sequenceHandle
+
+authorization for the sequence
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_MAX_BUFFER
+
+buffer
+
+data to be added to the Event
+
+Description
+
+Table 76 — TPM2_EventSequenceComplete Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPML_DIGEST_VALUES
+
+results
+
+Page 148
+October 31, 2013
+
+list of digests computed for the PCR
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+19.6.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "EventSequenceComplete_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+PCR extension is not allowed at the current locality
+
+TPM_RC_MODE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+input handle is not a valid event sequence object
+
+TPM_RC
+TPM2_EventSequenceComplete(
+EventSequenceComplete_In
+EventSequenceComplete_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+HASH_OBJECT
+UINT32
+TPM_ALG_ID
+
+result;
+*hashObject;
+i;
+hashAlg;
+
+// Input validation
+// get the event sequence object pointer
+hashObject = (HASH_OBJECT *)ObjectGet(in->sequenceHandle);
+// input handle must reference an event sequence object
+if(hashObject->attributes.eventSeq != SET)
+return TPM_RC_MODE + RC_EventSequenceComplete_sequenceHandle;
+// see if a PCR extend is requested in call
+if(in->pcrHandle != TPM_RH_NULL)
+{
+// see if extend of the PCR is allowed at the locality of the command,
+if(!PCRIsExtendAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// if an extend is going to take place, then check to see if there has
+// been an orderly shutdown. If so, and the selected PCR is one of the
+// state saved PCR, then the orderly state has to change. The orderly state
+// does not change for PCR that are not preserved.
+// NOTE: This doesn't just check for Shutdown(STATE) because the orderly
+// state will have to change if this is a state-saved PCR regardless
+// of the current state. This is because a subsequent Shutdown(STATE) will
+// check to see if there was an orderly shutdown and not do anything if
+// there was. So, this must indicate that a future Shutdown(STATE) has
+// something to do.
+if(gp.orderlyState != SHUTDOWN_NONE && PCRIsStateSaved(in->pcrHandle))
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+}
+// Command Output
+out->results.count = 0;
+for(i = 0; i < HASH_COUNT; i++)
+{
+hashAlg = CryptGetHashAlgByIndex(i);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 149
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+Trusted Platform Module Library
+
+// Update last piece of data
+CryptUpdateDigest2B(&hashObject->state.hashState[i], &in->buffer.b);
+// Complete hash
+out->results.digests[out->results.count].hashAlg = hashAlg;
+CryptCompleteHash(&hashObject->state.hashState[i],
+CryptGetHashDigestSize(hashAlg),
+(BYTE *) &out->results.digests[out->results.count].digest);
+// Extend PCR
+if(in->pcrHandle != TPM_RH_NULL)
+PCRExtend(in->pcrHandle, hashAlg,
+CryptGetHashDigestSize(hashAlg),
+(BYTE *) &out->results.digests[out->results.count].digest);
+out->results.count++;
+}
+// Internal Data Update
+// mark sequence object as evict so it will be flushed on the way out
+hashObject->attributes.evict = SET;
+return TPM_RC_SUCCESS;
+}
+
+Page 150
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Attestation Commands
+
+20
+20.1
+
+Introduction
+
+The attestation commands cause the TPM to sign an internally generated data structure. The contents of
+the data structure vary according to the command.
+For all signing commands, provisions are made for the caller to provide a scheme to be used for the
+signing operation. This scheme will be applied only if the scheme of the key is TPM_ALG_NULL. If the
+scheme for signHandle is not TPM_ALG_NULL, then inScheme.scheme shall be TPM_ALG_NULL or the
+same as scheme in the public area of the key. If the scheme for signHandle is TPM_ALG_NULL, then
+inScheme will be used for the signing operation and may not be TPM_ALG_NULL. The TPM shall return
+TPM_RC_SCHEME to indicate that the scheme is not appropriate.
+For a signing key that is not restricted, the caller may specify the scheme to be used as long as the
+scheme is compatible with the family of the key (for example, TPM_ALG_RSAPSS cannot be selected for
+an ECC key). If the caller sets scheme to TPM_ALG_NULL, then the default scheme of the key is used.
+If the handle for the signing key (signHandle) is TPM_RH_NULL, then all of the actions of the command
+are performed and the attestation block is “signed” with the NULL Signature.
+NOTE 1
+
+This mechanism is provided so that additional commands are not required to access the data that
+might be in an attestation structure.
+
+NOTE 2
+
+When signHandle is TPM_RH_NULL, scheme is still required to be a valid signing scheme (may be
+TPM_ALG_NULL), but the scheme will have no effect on the format of the signature. It will always
+be the NULL Signature.
+
+TPM2_NV_Certify() is an attestation command that is documented in 1. The remaining attestation
+commands are collected in the remainder of this clause.
+Each of the attestation structures contains a TPMS_CLOCK_INFO structure and a firmware version
+number. These values may be considered privacy-sensitive, because they would aid in the correlation of
+attestations by different keys. To provide improved privacy, the resetCount, restartCount, and
+firmwareVersion numbers are obfuscated when the signing key is not in the Endorsement or Platform
+hierarchies.
+The obfuscation value is computed by:
+
+obfuscation ≔ KDFa(signHandle→nameAlg, shProof, “OBFUSCATE”, signHandle→QN, 0, 128) (3)
+Of the returned 128 bits, 64 bits are added to the versionNumber field of the attestation structure; 32 bits
+are added to the clockInfo.resetCount and 32 bits are added to the clockInfo.restartCount. The order in
+which the bits are added is implementation-dependent.
+NOTE 3
+
+The obfuscation value for each signing key will be unique to that key in a specific location. That is,
+each version of a duplicated signing key will have a different obfuscation value.
+
+When the signing key is TPM_RH_NULL, the data structure is produced but not signed; and the values in
+the signed data structure are obfuscated. When computing the obfuscation value for TPM_RH_NULL, the
+hash used for context integrity is used.
+NOTE 4
+
+The QN for TPM_RH_NULL is TPM_RH_NULL.
+
+If the signing scheme of signHandle is an anonymous scheme, then the attestation blocks will not contain
+the Qualified Name of the signHandle.
+Each of the attestation structures allows the caller to provide some qualifying data (qualifyingData). For
+most signing schemes, this value will be placed in the TPMS_ATTEST.extraData parameter that is then
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 151
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+hashed and signed. However, for some schemes such as ECDAA, the qualifyingData is used in a
+different manner (for details, see “ECDAA” in Part 1).
+
+Page 152
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.2
+
+Part 3: Commands
+
+TPM2_Certify
+
+20.2.1 General Description
+The purpose of this command is to prove that an object with a specific Name is loaded in the TPM. By
+certifying that the object is loaded, the TPM warrants that a public area with a given Name is selfconsistent and associated with a valid sensitive area. If a relying party has a public area that has the
+same Name as a Name certified with this command, then the values in that public area are correct.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+Authorization for objectHandle requires ADMIN role authorization. If performed with a policy session, the
+session shall have a policySession→commandCode set to TPM_CC_Certify. This indicates that the
+policy that is being used is a policy that is for certification, and not a policy that would approve another
+use. That is, authority to use an object does not grant authority to certify the object.
+The object may be any object that is loaded with TPM2_Load() or TPM2_CreatePrimary(). An object that
+only has its public area loaded cannot be certified.
+NOTE 2
+
+The restriction occurs because the Name is used to identify the object being certified. If the TPM
+has not validated that the public area is associated with a matched sensitive area, then the public
+area may not represent a valid object a nd cannot be certified.
+
+The certification includes the Name and Qualified Name of the certified object as well as the Name and
+the Qualified Name of the certifying object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 153
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.2.2 Command and Response
+Table 77 — TPM2_Certify Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Certify
+
+TPMI_DH_OBJECT
+
+@objectHandle
+
+handle of the object to be certified
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the key used to sign the attestation structure
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+user provided qualifying data
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+Description
+
+Table 78 — TPM2_Certify Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+.
+
+TPM2B_ATTEST
+
+certifyInfo
+
+the structure that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the asymmetric signature over certifyInfo using the key
+referenced by signHandle
+
+Page 154
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "Certify_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is not compatible with signHandle
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+
+Meaning
+
+digest generated for inScheme is greater or has larger size than the
+modulus of signHandle, or the buffer for the result in signature is too
+small (for an RSA key); invalid commit status (for an ECC key with a
+split scheme).
+
+TPM_RC
+TPM2_Certify(
+Certify_In
+Certify_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMS_ATTEST
+
+result;
+certifyInfo;
+
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&certifyInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_Certify_signHandle;
+else
+return RcSafeAddToResult(result, RC_Certify_inScheme);
+}
+// Certify specific fields
+// Attestation type
+certifyInfo.type = TPM_ST_ATTEST_CERTIFY;
+// Certified object name
+certifyInfo.attested.certify.name.t.size =
+ObjectGetName(in->objectHandle,
+&certifyInfo.attested.certify.name.t.name);
+// Certified object qualified name
+ObjectGetQualifiedName(in->objectHandle,
+&certifyInfo.attested.certify.qualifiedName);
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned
+// by SignAttestInfo()
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&certifyInfo,
+&in->qualifyingData,
+&out->certifyInfo,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 155
+October 31, 2013
+
+ Part 3: Commands
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+
+Trusted Platform Module Library
+&out->signature);
+
+// TPM_RC_ATTRIBUTES cannot be returned here as FillInAttestInfo would already
+// have returned TPM_RC_KEY
+pAssert(result != TPM_RC_ATTRIBUTES);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 156
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.3
+
+Part 3: Commands
+
+TPM2_CertifyCreation
+
+20.3.1 General Description
+This command is used to prove the association between an object and its creation data. The TPM will
+validate that the ticket was produced by the TPM and that the ticket validates the association between a
+loaded public area and the provided hash of the creation data (creationHash).
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+The TPM will create a test ticket using the Name associated with objectHandle and creationHash as:
+
+HMAC(proof, (TPM_ST_CREATION || objectHandle→Name || creationHash))
+
+(4)
+
+This ticket is then compared to creation ticket. If the tickets are not the same, the TPM shall return
+TPM_RC_TICKET.
+If the ticket is valid, then the TPM will create a TPMS_ATTEST structure and place creationHash of the
+command in the creationHash field of the structure. The Name associated with objectHandle will be
+included in the attestation data that is then signed using the key associated with signHandle.
+NOTE 2
+
+If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
+Signature.
+
+ObjectHandle may be any object that is loaded with TPM2_Load() or TPM2_CreatePrimary().
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 157
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.3.2 Command and Response
+Table 79 — TPM2_CertifyCreation Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_CertifyCreation
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the key that will sign the attestation block
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+objectHandle
+
+the object associated with the creation data
+Auth Index: None
+
+TPM2B_DATA
+
+qualifyingData
+
+user-provided qualifying data
+
+TPM2B_DIGEST
+
+creationHash
+
+hash of the creation data produced by TPM2_Create()
+or TPM2_CreatePrimary()
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPMT_TK_CREATION
+
+creationTicket
+
+ticket produced by TPM2_Create() or
+TPM2_CreatePrimary()
+
+Table 80 — TPM2_CertifyCreation Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+certifyInfo
+
+the structure that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over certifyInfo
+
+Page 158
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "CertifyCreation_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is not compatible with signHandle
+
+TPM_RC_TICKET
+
+creationTicket does not match objectHandle
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+digest generated for inScheme is greater or has larger size than the
+modulus of signHandle, or the buffer for the result in signature is too
+small (for an RSA key); invalid commit status (for an ECC key with a
+split scheme).
+
+TPM_RC
+TPM2_CertifyCreation(
+CertifyCreation_In
+CertifyCreation_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPM2B_NAME
+TPMT_TK_CREATION
+TPMS_ATTEST
+
+result;
+name;
+ticket;
+certifyInfo;
+
+// Input Validation
+// CertifyCreation specific input validation
+// Get certified object name
+name.t.size = ObjectGetName(in->objectHandle, &name.t.name);
+// Re-compute ticket
+TicketComputeCreation(in->creationTicket.hierarchy, &name,
+&in->creationHash, &ticket);
+// Compare ticket
+if(!Memory2BEqual(&ticket.digest.b, &in->creationTicket.digest.b))
+return TPM_RC_TICKET + RC_CertifyCreation_creationTicket;
+// Command Output
+// Common fields
+result = FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
+&certifyInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_CertifyCreation_signHandle;
+else
+return RcSafeAddToResult(result, RC_CertifyCreation_inScheme);
+}
+// CertifyCreation specific fields
+// Attestation type
+certifyInfo.type = TPM_ST_ATTEST_CREATION;
+certifyInfo.attested.creation.objectName = name;
+// Copy the creationHash
+certifyInfo.attested.creation.creationHash = in->creationHash;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 159
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+
+Trusted Platform Module Library
+
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+// this point
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&certifyInfo,
+&in->qualifyingData,
+&out->certifyInfo,
+&out->signature);
+// TPM_RC_ATTRIBUTES cannot be returned here as FillInAttestInfo would already
+// have returned TPM_RC_KEY
+pAssert(result != TPM_RC_ATTRIBUTES);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 160
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.4
+
+Part 3: Commands
+
+TPM2_Quote
+
+20.4.1 General Description
+This command is used to quote PCR values.
+NOTE
+
+See 20.1 for description of how the signing scheme is selected.
+
+The TPM will hash the list of PCR selected by PCRselect using the hash algorithm associated with
+signHandle (this is the hash algorithm of the signing scheme, not the nameAlg of signHandle).
+The digest is computed as the hash of the concatenation of all of the digest values of the selected PCR.
+The concatenation of PCR is described in Part 1, Selecting Multiple PCR.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 161
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.4.2 Command and Response
+Table 81 — TPM2_Quote Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Quote
+
+TPMI_DH_OBJECT
+
+@signHandle
+
+handle of key that will perform signature
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+data supplied by the caller
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+TPML_PCR_SELECTION
+
+PCRselect
+
+PCR set to quote
+
+Table 82 — TPM2_Quote Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+quoted
+
+the quoted information
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over quoted
+
+Page 162
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.4.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "Quote_fp.h"
+Error Returns
+TPM_RC_KEY
+
+signHandle does not reference a signing key;
+
+TPM_RC_SCHEME
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+the scheme is not compatible with sign key type, or input scheme is
+not compatible with default scheme, or the chosen scheme is not a
+valid sign scheme
+
+TPM_RC
+TPM2_Quote(
+Quote_In
+Quote_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMI_ALG_HASH
+TPMS_ATTEST
+
+result;
+hashAlg;
+quoted;
+
+// Command Output
+// Filling in attest information
+// Common fields
+// FillInAttestInfo will return TPM_RC_SCHEME or TPM_RC_KEY
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&quoted);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_Quote_signHandle;
+else
+return RcSafeAddToResult(result, RC_Quote_inScheme);
+}
+// Quote specific fields
+// Attestation type
+quoted.type = TPM_ST_ATTEST_QUOTE;
+// Get hash algorithm in sign scheme. This hash algorithm is used to
+// compute PCR digest. If there is no algorithm, then the PCR cannot
+// be digested and this command returns TPM_RC_SCHEME
+hashAlg = in->inScheme.details.any.hashAlg;
+if(hashAlg == TPM_ALG_NULL)
+return TPM_RC_SCHEME + RC_Quote_inScheme;
+// Compute PCR digest
+PCRComputeCurrentDigest(hashAlg,
+&in->PCRselect,
+&quoted.attested.quote.pcrDigest);
+// Copy PCR select. "PCRselect" is modified in PCRComputeCurrentDigest
+// function
+quoted.attested.quote.pcrSelect = in->PCRselect;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 163
+October 31, 2013
+
+ Part 3: Commands
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+
+Trusted Platform Module Library
+
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES
+// error may be returned by SignAttestInfo.
+// NOTE: TPM_RC_ATTRIBUTES means that the key is not a signing key but that
+// was checked above and TPM_RC_KEY was returned. TPM_RC_VALUE means that the
+// value to sign is too large but that means that the digest is too big and
+// that can't happen.
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&quoted,
+&in->qualifyingData,
+&out->quoted,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 164
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.5
+
+Part 3: Commands
+
+TPM2_GetSessionAuditDigest
+
+20.5.1 General Description
+This command returns a digital signature of the audit session digest.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+If sessionHandle is not an audit session, the TPM shall return TPM_RC_TYPE.
+NOTE 2
+
+A session does not become an audit session until the successful completion of the command in
+which the session is first used as an audit session.
+
+This command requires authorization from the privacy administrator of the TPM (expressed with
+endorsementAuth) as well as authorization to use the key associated with signHandle.
+If this command is audited, then the audit digest that is signed will not include the digest of this command
+because the audit digest is only updated when the command completes successfully.
+This command does not cause the audit session to be closed and does not reset the digest value.
+NOTE 3
+
+The audit session digest will be reset if the sessionHandle is used as the audit session for the
+command and the auditReset attribute of the session is set; and this command will be the first
+command in the audit digest.
+
+NOTE 4
+
+A reason for using 'sessionHahdle' in this command is so that the continueSession attribute may be
+CLEAR. This will flush the session at the end of the command.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 165
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.5.2 Command and Response
+Table 83 — TPM2_GetSessionAuditDigest Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetSessionAuditDigest
+
+TPMI_RH_ENDORSEMENT
+
+@privacyAdminHandle
+
+handle of the privacy administrator
+(TPM_RH_ENDORSEMENT)
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the signing key
+Auth Index: 2
+Auth Role: USER
+
+TPMI_SH_HMAC
+
+sessionHandle
+
+handle of the audit session
+Auth Index: None
+
+TPM2B_DATA
+
+qualifyingData
+
+user-provided qualifying data – may be zero-length
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+Description
+
+Table 84 — TPM2_GetSessionAuditDigest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+auditInfo
+
+the audit information that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over auditInfo
+
+Page 166
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "GetSessionAuditDigest_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is incompatible with signHandle type; or both scheme and
+key's default scheme are empty; or scheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from scheme
+
+TPM_RC_TYPE
+
+sessionHandle does not reference an audit session
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+digest generated for the given scheme is greater than the modulus of
+signHandle (for an RSA key); invalid commit status or failed to
+generate r value (for an ECC key)
+
+TPM_RC
+TPM2_GetSessionAuditDigest(
+GetSessionAuditDigest_In
+GetSessionAuditDigest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+SESSION
+TPMS_ATTEST
+
+result;
+*session;
+auditInfo;
+
+// Input Validation
+// SessionAuditDigest specific input validation
+// Get session pointer
+session = SessionGet(in->sessionHandle);
+// session must be an audit session
+if(session->attributes.isAudit == CLEAR)
+return TPM_RC_TYPE + RC_GetSessionAuditDigest_sessionHandle;
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&auditInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_GetSessionAuditDigest_signHandle;
+else
+return RcSafeAddToResult(result, RC_GetSessionAuditDigest_inScheme);
+}
+// SessionAuditDigest specific fields
+// Attestation type
+auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT;
+// Copy digest
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 167
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+
+Trusted Platform Module Library
+
+auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest;
+// Exclusive audit session
+if(g_exclusiveAuditSession == in->sessionHandle)
+auditInfo.attested.sessionAudit.exclusiveSession = TRUE;
+else
+auditInfo.attested.sessionAudit.exclusiveSession = FALSE;
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+// this point
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&auditInfo,
+&in->qualifyingData,
+&out->auditInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 168
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.6
+
+Part 3: Commands
+
+TPM2_GetCommandAuditDigest
+
+20.6.1 General Description
+This command returns the current value of the command audit digest, a digest of the commands being
+audited, and the audit hash algorithm. These values are placed in an attestation structure and signed with
+the key referenced by signHandle.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+When this command completes successfully, and signHandle is not TPM_RH_NULL, the audit digest is
+cleared.
+NOTE 2
+
+The way that the TPM tracks that the digest is clear is vendor -dependent. The reference
+implementation resets the size of the digest to zero.
+
+If this command is being audited, then the signed digest produced by the command will not include the
+command. At the end of this command, the audit digest will be extended with cpHash and the rpHash of
+the command which would change the command audit digest signed by the next invocation of this
+command.
+This command requires authorization from the privacy administrator of the TPM (expressed with
+endorsementAuth) as well as authorization to use the key associated with signHandle.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 169
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.6.2 Command and Response
+Table 85 — TPM2_GetCommandAuditDigest Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetCommandAuditDigest {NV}
+
+TPMI_RH_ENDORSEMENT
+
+@privacyHandle
+
+handle of the privacy administrator
+(TPM_RH_ENDORSEMENT)
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+the handle of the signing key
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+other data to associate with this audit digest
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+Table 86 — TPM2_GetCommandAuditDigest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ATTEST
+
+auditInfo
+
+the auditInfo that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over auditInfo
+
+Page 170
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "GetCommandAuditDigest_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is incompatible with signHandle type; or both scheme and
+key's default scheme are empty; or scheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from scheme
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+digest generated for the given scheme is greater than the modulus of
+signHandle (for an RSA key); invalid commit status or failed to
+generate r value (for an ECC key)
+
+TPM_RC
+TPM2_GetCommandAuditDigest(
+GetCommandAuditDigest_In
+GetCommandAuditDigest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMS_ATTEST
+
+result;
+auditInfo;
+
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&auditInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_GetCommandAuditDigest_signHandle;
+else
+return RcSafeAddToResult(result, RC_GetCommandAuditDigest_inScheme);
+}
+// CommandAuditDigest specific fields
+// Attestation type
+auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT;
+// Copy audit hash algorithm
+auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg;
+// Copy counter value
+auditInfo.attested.commandAudit.auditCounter = gp.auditCounter;
+// Copy command audit log
+auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest;
+CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest);
+//
+//
+//
+//
+
+Sign attestation structure. A NULL signature will be returned if
+signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+this point
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 171
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+
+Trusted Platform Module Library
+
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&auditInfo,
+&in->qualifyingData,
+&out->auditInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+if(in->signHandle != TPM_RH_NULL)
+{
+// Reset log
+gr.commandAuditDigest.t.size = 0;
+// orderly state should be cleared because of the update in
+// commandAuditDigest, as well as the reporting of clock info
+g_clearOrderly = TRUE;
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 172
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+20.7
+
+Part 3: Commands
+
+TPM2_GetTime
+
+20.7.1 General Description
+This command returns the current values of Time and Clock.
+NOTE 1
+
+See 20.1 for description of how the signing scheme is selected.
+
+The values of Clock, resetCount and restartCount appear in two places in timeInfo: once in
+TPMS_ATTEST.clockInfo and again in TPMS_ATTEST.attested.time.clockInfo. The firmware version
+number
+also
+appears
+in
+two
+places
+(TPMS_ATTEST.firmwareVersion
+and
+TPMS_ATTEST.attested.time.firmwareVersion). If signHandle is in the endorsement or platform
+hierarchies, both copies of the data will be the same. However, if signHandle is in the storage hierarchy or
+is TPM_RH_NULL, the values in TPMS_ATTEST.clockInfo and TPMS_ATTEST.firmwareVersion are
+obfuscated but the values in TPM_ATTEST.attested.time are not.
+NOTE 2
+
+The purpose of this duplication is to allow an entity who is trusted by the privacy Administrator to
+correlate the obfuscated values with the clear -text values.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 173
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+20.7.2 Command and Response
+Table 87 — TPM2_GetTime Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetTime
+
+TPMI_RH_ENDORSEMENT
+
+@privacyAdminHandle
+
+handle of the privacy administrator
+(TPM_RH_ENDORSEMENT)
+Auth Index: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+the keyHandle identifier of a loaded key that can
+perform digital signatures
+Auth Index: 2
+Auth Role: USER
+
+TPM2B_DATA
+
+qualifyingData
+
+data to tick stamp
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+Description
+
+Table 88 — TPM2_GetTime Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+.
+
+TPM2B_ATTEST
+
+timeInfo
+
+standard TPM-generated attestation block
+
+TPMT_SIGNATURE
+
+signature
+
+the signature over timeInfo
+
+Page 174
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+20.7.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Attest_spt_fp.h"
+#include "GetTime_fp.h"
+Error Returns
+TPM_RC_KEY
+
+key referenced by signHandle is not a signing key
+
+TPM_RC_SCHEME
+
+inScheme is incompatible with signHandle type; or both scheme and
+key's default scheme are empty; or scheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from scheme
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+digest generated for the given scheme is greater than the modulus of
+signHandle (for an RSA key); invalid commit status or failed to
+generate r value (for an ECC key)
+
+TPM_RC
+TPM2_GetTime(
+GetTime_In
+GetTime_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+TPMS_ATTEST
+
+result;
+timeInfo;
+
+// Command Output
+// Filling in attest information
+// Common fields
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&timeInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_GetTime_signHandle;
+else
+return RcSafeAddToResult(result, RC_GetTime_inScheme);
+}
+// GetClock specific fields
+// Attestation type
+timeInfo.type = TPM_ST_ATTEST_TIME;
+// current clock in plain text
+timeInfo.attested.time.time.time = g_time;
+TimeFillInfo(&timeInfo.attested.time.time.clockInfo);
+// Firmware version in plain text
+timeInfo.attested.time.firmwareVersion
+= ((UINT64) gp.firmwareV1) << 32;
+timeInfo.attested.time.firmwareVersion += gp.firmwareV2;
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
+// TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
+// this point
+result = SignAttestInfo(in->signHandle,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 175
+October 31, 2013
+
+ Part 3: Commands
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+
+Trusted Platform Module Library
+
+&in->inScheme,
+&timeInfo,
+&in->qualifyingData,
+&out->timeInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 176
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+21
+
+Part 3: Commands
+
+Ephemeral EC Keys
+
+21.1
+
+Introduction
+
+The TPM generates keys that have different lifetimes. TPM keys in a hierarchy can be persistent for as
+long as the seed of the hierarchy is unchanged and these keys may be used multiple times. Other TPMgenerated keys are only useful for a single operation. Some of these single-use keys are used in the
+command in which they are created. Examples of this use are TPM2_Duplicate() where an ephemeral
+key is created for a single pass key exchange with another TPM. However, there are other cases, such
+as anonymous attestation, where the protocol requires two passes where the public part of the ephemeral
+key is used outside of the TPM before the final command "consumes" the ephemeral key.
+For these uses, TPM2_Commit() or TPM2_EC_Ephemeral() may be used to have the TPM create an
+ephemeral EC key and return the public part of the key for external use. Then in a subsequent command,
+the caller provides a reference to the ephemeral key so that the TPM can retrieve or recreate the
+associated private key.
+When an ephemeral EC key is created, it is assigned a number and that number is returned to the caller
+as the identifier for the key. This number is not a handle. A handle is assigned to a key that may be
+context saved but these ephemeral EC keys may not be saved and do not have a full key context. When
+a subsequent command uses the ephemeral key, the caller provides the number of the ephemeral key.
+The TPM uses that number to either look up or recompute the associated private key. After the key is
+used, the TPM records the fact that the key has been used so that it cannot be used again.
+As mentioned, the TPM can keep each assigned private ephemeral key in memory until it is used.
+However, this could consume a large amount of memory. To limit the memory size, the TPM is allowed to
+restrict the number of pending private keys – keys that have been allocated but not used.
+NOTE
+
+The minimum number of ephemeral keys is determined by a platform specific specification
+
+To further reduce the memory requirements for the ephemeral private keys, the TPM is allowed to use
+pseudo-random values for the ephemeral keys. Instead of keeping the full value of the key in memory, the
+TPM can use a counter as input to a KDF. Incrementing the counter will cause the TPM to generate a
+new pseudo-random value.
+Using the counter to generate pseudo-random private ephemeral keys greatly simplifies tracking of key
+usage. When a counter value is used to create a key, a bit in an array may be set to indicate that the key
+use is pending. When the ephemeral key is consumed, the bit is cleared. This prevents the key from
+being used more than once.
+Since the TPM is allowed to restrict the number of pending ephemeral keys, the array size can be limited.
+For example, a 128 bit array would allow 128 keys to be "pending".
+The management of the array is described in greater detail in the Split Operations clause in Annex C of
+part 1.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 177
+October 31, 2013
+
+ Part 3: Commands
+
+21.2
+
+Trusted Platform Module Library
+
+TPM2_Commit
+
+21.2.1 General Description
+TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM will perform
+the point multiplications on the provided points and return intermediate signing values. The signHandle
+parameter shall refer to an ECC key with the sign attribute (TPM_RC_ATTRIBUTES) using an
+anonymous signing scheme (TPM_RC_SCHEME).
+For this command, p1, s2 and y2 are optional parameters. If s2 is an Empty Buffer, then the TPM shall
+return TPM_RC_SIZE if y2 is not an Empty Buffer. If p1, s2, and y2 are all Empty Buffers, the TPM shall
+return TPM_RC_NO_RESULT.
+In the algorithm below, the following additional values are used in addition to the command parameters:
+
+HnameAlg
+
+hash function using the nameAlg of the key associated with
+signHandle
+
+p
+
+field modulus of the curve associated with signHandle
+
+n
+
+order of the curve associated with signHandle
+
+ds
+
+private key associated with signHandle
+
+c
+
+counter that increments each time a TPM2_Commit() is
+successfully completed
+
+A[i]
+
+array of bits used to indicate when a value of c has been used in
+a signing operation; values of i are 0 to 2n-1
+
+k
+
+nonce that is set to a random value on each TPM Reset; nonce
+size is twice the security strength of any ECDAA key supported
+by the TPM.
+
+The algorithm is:
+a) set K, L, and E to be Empty Buffers.
+b) if s2 is not an Empty Buffer, compute x2 ≔ HnameAlg (s2) mod p, else skip to step (e)
+c) if (x2, y2) is not a point on the curve of signHandle, return TPM_RC_ECC_POINT
+d) set K ≔ [ds] (x2, y2)
+e) generate or derive r (see the "Commit Random Value" clause in Part 1)
+f)
+
+set r ≔ r mod n
+
+NOTE 1
+
+nLen is the number of bits in n
+
+g) if p1 is an Empty Buffer, skip to step i)
+h) if (p1) is not a point on the curve of signHandle, return TPM_RC_ECC_POINT
+i)
+
+set E ≔ [r] (p1)
+
+j)
+
+if K is not an Empty Buffer, set L ≔ [r] (x2, y2)
+
+k) if K, L, or E is the point at infinity, return TPM_RC_NO_RESULT
+l)
+
+set counter ≔ commitCount
+
+m) set commitCount ≔ commitCount + 1
+
+Page 178
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+NOTE 2
+
+Part 3: Commands
+
+Depending on the method of generating r, it may be necessary to update the tracking array here.
+
+n) output K, L, E and counter
+NOTE 3
+
+Depending on the input parameters K and L may be Empty Buffers or E may be an Empty Buffer
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 179
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+21.2.2 Command and Response
+Table 89 — TPM2_Commit Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+paramSize
+
+TPM_CC
+
+commandCode
+
+Description
+
+TPM_CC_Commit
+handle of the key that will be used in the signing
+operation
+
+TPMI_DH_OBJECT
+
+@signHandle
+
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_ECC_POINT
+
+P1
+
+a point (M) on the curve used by signHandle
+
+TPM2B_SENSITIVE_DATA
+
+s2
+
+octet array used to derive x-coordinate of a base point
+
+TPM2B_ECC_PARAMETER
+
+y2
+
+y coordinate of the point associated with s2
+
+Table 90 — TPM2_Commit Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see 8
+
+UINT32
+
+paramSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+K
+
+ECC point K ≔ [ds](x2, y2)
+
+TPM2B_ECC_POINT
+
+L
+
+ECC point L ≔ [r](x2, y2)
+
+TPM2B_ECC_POINT
+
+E
+
+ECC point E ≔ [r]P1
+
+UINT16
+
+counter
+
+least-significant 16 bits of commitCount
+
+Page 180
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+21.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Commit_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+TPM_RC_ATTRIBUTES
+
+keyHandle references a restricted key that is not a signing key
+
+TPM_RC_ECC_POINT
+
+either P1 or the point derived from s2 is not on the curve of
+keyHandle
+
+TPM_RC_HASH
+
+invalid name algorithm in keyHandle
+
+TPM_RC_KEY
+
+keyHandle does not reference an ECC key
+
+TPM_RC_SCHEME
+
+keyHandle references a restricted signing key that does not use and
+anonymous scheme
+
+TPM_RC_NO_RESULT
+
+K, L or E was a point at infinity; or failed to generate r value
+
+TPM_RC_SIZE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
+Meaning
+
+s2 is empty but y2 is not or s2 provided but y2 is not
+
+TPM_RC
+TPM2_Commit(
+Commit_In
+Commit_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+OBJECT
+TPMS_ECC_POINT
+TPMS_ECC_POINT
+TPMS_ECC_POINT
+TPM2B_ECC_PARAMETER
+TPM2B
+TPM_RC
+UINT16
+
+*eccKey;
+P2;
+*pP2 = NULL;
+*pP1 = NULL;
+r;
+*p;
+result;
+hashResults;
+
+// Input Validation
+eccKey = ObjectGet(in->signHandle);
+// Input key must be an ECC key
+if(eccKey->publicArea.type != TPM_ALG_ECC)
+return TPM_RC_KEY + RC_Commit_signHandle;
+// if the key is restricted, it must be a signing key using an anonymous scheme
+if(eccKey->publicArea.objectAttributes.restricted == SET)
+{
+if(eccKey->publicArea.objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_Commit_signHandle;
+if(!CryptIsSchemeAnonymous(
+eccKey->publicArea.parameters.eccDetail.scheme.scheme))
+return TPM_RC_SCHEME + RC_Commit_signHandle;
+}
+else
+{
+// if not restricted, s2, and y2 must be an Empty Buffer
+if(in->s2.t.size)
+return TPM_RC_SIZE + RC_Commit_s2;
+}
+// Make sure that both parts of P2 are present if either is present
+if((in->s2.t.size == 0) != (in->y2.t.size == 0))
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 181
+October 31, 2013
+
+ Part 3: Commands
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
+Trusted Platform Module Library
+
+return TPM_RC_SIZE + RC_Commit_y2;
+// Get prime modulus for the curve. This is needed later but getting this now
+// allows confirmation that the curve exists
+p = (TPM2B *)CryptEccGetParameter('p',
+eccKey->publicArea.parameters.eccDetail.curveID);
+// if no p, then the curve ID is bad
+// NOTE: This should never occur if the input unmarshaling code is working
+// correctly
+if(p == NULL)
+return TPM_RC_KEY + RC_Commit_signHandle;
+// Get the random value that will be used in the point multiplications
+// Note: this does not commit the count.
+if(!CryptGenerateR(&r,
+NULL,
+eccKey->publicArea.parameters.eccDetail.curveID,
+&eccKey->name))
+return TPM_RC_NO_RESULT;
+// Set up P2 if s2 and Y2 are provided
+if(in->s2.t.size != 0)
+{
+pP2 = &P2;
+// copy y2 for P2
+MemoryCopy2B(&P2.y.b, &in->y2.b, sizeof(P2.y.t.buffer));
+// Compute x2 HnameAlg(s2) mod p
+//
+do the hash operation on s2 with the size of curve 'p'
+hashResults = CryptHashBlock(eccKey->publicArea.nameAlg,
+in->s2.t.size,
+in->s2.t.buffer,
+p->size,
+P2.x.t.buffer);
+// If there were error returns in the hash routine, indicate a problem
+// with the hash in
+if(hashResults == 0)
+return TPM_RC_HASH + RC_Commit_signHandle;
+// set the size of the X value to the size of the hash
+P2.x.t.size = hashResults;
+// set p2.x = hash(s2) mod p
+if(CryptDivide(&P2.x.b, p, NULL, &P2.x.b) != TPM_RC_SUCCESS)
+return TPM_RC_NO_RESULT;
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+pP2))
+return TPM_RC_ECC_POINT + RC_Commit_s2;
+if(eccKey->attributes.publicOnly == SET)
+return TPM_RC_KEY + RC_Commit_signHandle;
+}
+else
+// If there is a P1, make sure that it is on the curve
+// NOTE: an "empty" point has two UINT16 values which are the size values
+// for each of the coordinates.
+if(in->P1.t.size > 4)
+{
+
+Page 182
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+
+Part 3: Commands
+
+pP1 = &in->P1.t.point;
+if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
+pP1))
+return TPM_RC_ECC_POINT + RC_Commit_P1;
+}
+// Pass the parameters to CryptCommit.
+// The work is not done inline because it does several point multiplies
+// with the same curve. There is significant optimization by not
+// having to reload the curve parameters multiple times.
+result = CryptCommitCompute(&out->K.t.point,
+&out->L.t.point,
+&out->E.t.point,
+eccKey->publicArea.parameters.eccDetail.curveID,
+pP1,
+pP2,
+&eccKey->sensitive.sensitive.ecc,
+&r);
+if(result != TPM_RC_SUCCESS)
+return result;
+out->K.t.size = TPMS_ECC_POINT_Marshal(&out->K.t.point, NULL, NULL);
+out->L.t.size = TPMS_ECC_POINT_Marshal(&out->L.t.point, NULL, NULL);
+out->E.t.size = TPMS_ECC_POINT_Marshal(&out->E.t.point, NULL, NULL);
+// The commit computation was successful so complete the commit by setting
+// the bit
+out->counter = CryptCommit();
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 183
+October 31, 2013
+
+ Part 3: Commands
+
+21.3
+
+Trusted Platform Module Library
+
+TPM2_EC_Ephemeral
+
+21.3.1 General Description
+TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol.
+The TPM will use the commit mechanism to assign an ephemeral key r and compute a public point Q ≔
+[r]G where G is the generator point associated with curveID.
+
+Page 184
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+21.3.2 Command and Response
+Table 91 — TPM2_EC_Ephemeral Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+paramSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EC_Ephemeral
+
+TPMI_ECC_CURVE
+
+curveID
+
+The curve for the computed ephemeral point
+
+Table 92 — TPM2_EC_Ephemeral Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see 8
+
+UINT32
+
+paramSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_ECC_POINT
+
+Q
+
+ephemeral public key Q ≔ [r]G
+
+UINT16
+
+counter
+
+least-significant 16 bits of commitCount
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 185
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+21.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "EC_Ephemeral_fp.h"
+#ifdef TPM_ALG_ECC
+Error Returns
+none
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
+Meaning
+...
+
+TPM_RC
+TPM2_EC_Ephemeral(
+EC_Ephemeral_In
+EC_Ephemeral_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM2B_ECC_PARAMETER
+
+r;
+
+// Get the random value that will be used in the point multiplications
+// Note: this does not commit the count.
+if(!CryptGenerateR(&r,
+NULL,
+in->curveID,
+NULL))
+return TPM_RC_NO_RESULT;
+CryptEccPointMultiply(&out->Q.t.point, in->curveID, &r, NULL);
+// commit the count value
+out->counter = CryptCommit();
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 186
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+22
+
+Part 3: Commands
+
+Signing and Signature Verification
+
+22.1
+
+TPM2_VerifySignature
+
+22.1.1 General Description
+This command uses loaded keys to validate a signature on a message with the message digest passed
+to the TPM.
+If the signature check succeeds, then the TPM will produce a TPMT_TK_VERIFIED. Otherwise, the TPM
+shall return TPM_RC_SIGNATURE.
+NOTE 1
+
+A valid ticket may be used in subsequent commands to provide proof to the TPM that the TPM has
+validated the signature over the message using the key referenced by keyHandle.
+
+If keyHandle references an asymmetric key, only the public portion of the key needs to be loaded. If
+keyHandle references a symmetric key, both the public and private portions need to be loaded.
+NOTE 2
+
+The sensitive area of the symmetric object is required to allow verification of the symmetric
+signature (the HMAC).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 187
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+22.1.2 Command and Response
+Table 93 — TPM2_VerifySignature Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_VerifySignature
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+handle of public key that will be used in the validation
+Auth Index: None
+
+TPM2B_DIGEST
+
+digest
+
+digest of the signed message
+
+TPMT_SIGNATURE
+
+signature
+
+signature to be tested
+
+Table 94 — TPM2_VerifySignature Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMT_TK_VERIFIED
+
+validation
+
+Page 188
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+22.1.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "VerifySignature_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+keyHandle does not reference a signing key
+
+TPM_RC_SIGNATURE
+
+signature is not genuine
+
+TPM_RC_SCHEME
+
+CryptVerifySignature()
+
+TPM_RC_HANDLE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+the input handle is not a sign key with private portion loaded
+
+TPM_RC
+TPM2_VerifySignature(
+VerifySignature_In
+VerifySignature_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+TPM2B_NAME
+OBJECT
+TPMI_RH_HIERARCHY
+
+result;
+name;
+*signObject;
+hierarchy;
+
+)
+{
+
+// Input Validation
+// Get sign object pointer
+signObject = ObjectGet(in->keyHandle);
+// The object to validate the signature must be a signing key.
+if(signObject->publicArea.objectAttributes.sign != SET)
+return TPM_RC_ATTRIBUTES + RC_VerifySignature_keyHandle;
+// If it doesn't have a sensitive area loaded
+// then it can't be a keyed hash signing key
+if(
+signObject->attributes.publicOnly == SET
+&& signObject->publicArea.type == TPM_ALG_KEYEDHASH
+)
+return TPM_RC_HANDLE + RC_VerifySignature_keyHandle;
+// Validate Signature. A TPM_RC_BINDING, TPM_RC_SCHEME or TPM_RC_SIGNATURE
+// error may be returned by CryptCVerifySignatrue()
+result = CryptVerifySignature(in->keyHandle, &in->digest, &in->signature);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_VerifySignature_signature);
+// Command Output
+hierarchy = ObjectGetHierarchy(in->keyHandle);
+if(
+hierarchy == TPM_RH_NULL
+|| signObject->publicArea.nameAlg == TPM_ALG_NULL)
+{
+// produce empty ticket if hierarchy is TPM_RH_NULL or nameAlg is
+// TPM_ALG_NULL
+out->validation.tag = TPM_ST_VERIFIED;
+out->validation.hierarchy = TPM_RH_NULL;
+out->validation.digest.t.size = 0;
+}
+else
+{
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 189
+October 31, 2013
+
+ Part 3: Commands
+50
+51
+52
+53
+54
+55
+56
+57
+
+Trusted Platform Module Library
+
+// Get object name that verifies the signature
+name.t.size = ObjectGetName(in->keyHandle, &name.t.name);
+// Compute ticket
+TicketComputeVerified(hierarchy, &in->digest, &name, &out->validation);
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 190
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+22.2
+
+Part 3: Commands
+
+TPM2_Sign
+
+22.2.1 General Description
+This command causes the TPM to sign an externally provided hash with the specified asymmetric signing
+key.
+NOTE 1
+
+Symmetric “signing” is done with an HMAC.
+
+If keyHandle references a restricted signing key, then validation shall be provided indicating that the TPM
+performed the hash of the data and validation shall indicate that hashed data did not start with
+TPM_GENERATED_VALUE.
+NOTE 2
+
+If the hashed data did start with TPM_GENERATED_VALUE, then the validation will be a NULL
+ticket.
+
+If the scheme of keyHandle is not TPM_ALG_NULL, then inScheme shall either be the same scheme as
+keyHandle or TPM_ALG_NULL.
+If the scheme of keyHandle is TPM_ALG_NULL, the TPM will sign using inScheme; otherwise, it will sign
+using the scheme of keyHandle.
+NOTE 3
+
+When the signing scheme requires a hash algorithm, the hash is defined in the qualifying data of the
+scheme.
+
+If inScheme is not a valid signing scheme for the type of keyHandle (or TPM_ALG_NULL), then the TPM
+shall return TPM_RC_SCHEME.
+If the scheme of keyHandle is an anonymous scheme, then inScheme shall have the same scheme
+algorithm as keyHandle and inScheme will contain a counter value that will be used in the signing
+process.
+As long as it is no larger than allowed, the digest parameter is not required to have any specific size but
+the signature operation may fail if digest is too large for the selected scheme.
+If the validation parameter is not the Empty Buffer, then it will be checked even if the key referenced by
+keyHandle is not a restricted signing key.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 191
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+22.2.2 Command and Response
+Table 95 — TPM2_Sign Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Sign
+
+TPMI_DH_OBJECT
+
+@keyHandle
+
+Handle of key that will perform signing
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+digest
+
+digest to be signed
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for keyHandle is
+TPM_ALG_NULL
+
+TPMT_TK_HASHCHECK
+
+validation
+
+proof that digest was created by the TPM
+If keyHandle is not a restricted signing key, then this
+may be a NULL Ticket with tag =
+TPM_ST_CHECKHASH.
+
+Description
+
+Table 96 — TPM2_Sign Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMT_SIGNATURE
+
+signature
+
+Page 192
+October 31, 2013
+
+the signature
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+22.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Sign_fp.h"
+#include "Attest_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+key referenced by keHandle is not a signing key
+
+TPM_RC_BINDING
+
+The public and private portions of the key are not properly bound.
+
+TPM_RC_SCHEME
+
+inScheme is not compatible with keyHandle; both inScheme and
+key's default scheme are empty; or inScheme is empty while key's
+default scheme requires explicit input scheme (split signing); or nonempty default key scheme differs from inScheme
+
+TPM_RC_TICKET
+
+validation is not a valid ticket
+
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+the value to sign is larger than allowed for the type of keyHandle
+
+TPM_RC
+TPM2_Sign(
+Sign_In
+Sign_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+TPMT_TK_HASHCHECK
+OBJECT
+
+result;
+ticket;
+*signKey;
+
+)
+{
+
+// Input Validation
+// Get sign key pointer
+signKey = ObjectGet(in->keyHandle);
+// If validation is provided, or the key is restricted, check the ticket
+if(
+in->validation.digest.t.size != 0
+|| signKey->publicArea.objectAttributes.restricted == SET)
+{
+// Compute and compare ticket
+TicketComputeHashCheck(in->validation.hierarchy, &in->digest, &ticket);
+if(!Memory2BEqual(&in->validation.digest.b, &ticket.digest.b))
+return TPM_RC_TICKET + RC_Sign_validation;
+}
+// Command Output
+// pick a scheme for sign. If the input sign scheme is not compatible with
+// the default scheme, return an error.
+result = CryptSelectSignScheme(in->keyHandle, &in->inScheme);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_Sign_keyHandle;
+else
+return RcSafeAddToResult(result, RC_Sign_inScheme);
+}
+// Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or TPM_RC_ATTRIBUTES
+// error may be returned at this point
+result = CryptSign(in->keyHandle, &in->inScheme, &in->digest, &out->signature);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 193
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+
+Trusted Platform Module Library
+
+return result;
+}
+
+Page 194
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+23
+
+Part 3: Commands
+
+Command Audit
+
+23.1
+
+Introduction
+
+If a command has been selected for command audit, the command audit status will be updated when that
+command completes successfully. The digest is updated as:
+
+commandAuditDigestnew ≔ HauditAlg(commandAuditDigestold || cpHash || rpHash)
+
+(5)
+
+where
+
+HauditAlg
+
+hash function using the algorithm of the audit sequence
+
+commandAuditDigest
+
+accumulated digest
+
+cpHash
+
+the command parameter hash
+
+rpHash
+
+the response parameter hash
+
+TPM2_Shutdown() cannot be audited but TPM2_Startup() can be audited. If the cpHash of the
+TPM2_Startup() is TPM_SU_STATE, that would indicate that a TPM2_Shutdown() had been successfully
+executed.
+TPM2_SetCommandCodeAuditStatus() is always audited.
+If the TPM is in Failure mode, command audit is not functional.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 195
+October 31, 2013
+
+ Part 3: Commands
+
+23.2
+
+Trusted Platform Module Library
+
+TPM2_SetCommandCodeAuditStatus
+
+23.2.1 General Description
+This command may be used by the Privacy Administrator or platform to change the audit status of a
+command or to set the hash algorithm used for the audit digest, but not both at the same time.
+If the auditAlg parameter is a supported hash algorithm and not the same as the current algorithm, then
+the TPM will check both setList and clearList are empty (zero length). If so, then the algorithm is changed,
+and the audit digest is cleared. If auditAlg is TPM_ALG_NULL or the same as the current algorithm, then
+the algorithm and audit digest are unchanged and the setList and clearList will be processed.
+NOTE 1
+
+Because the audit digest is cleared, the audit counter will increment the next time that an audited
+command is executed.
+
+Use of TPM2_SetCommandCodeAuditStatus() to change the list of audited commands is an audited
+event. If TPM_CC_SetCommandCodeAuditStatus is in clearList, it is ignored.
+NOTE 2
+
+Use of this command to change the audit hash algorithm is not audited and the digest is reset when
+the command completes. The change in the audit hash algorithm is the evidence that this command
+was used to change the algorithm.
+
+The commands in setList indicate the commands that to be added to the list of audited commands and
+the commands in clearList indicate the commands that will no longer be audited. It is not an error if a
+command in setList is already audited or is not implemented. It is not an error if a command in clearList is
+not currently being audited or is not implemented.
+If a command code is in both setList and clearList, then it will not be audited (that is, setList shall be
+processed first).
+
+Page 196
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+23.2.2 Command and Response
+Table 97 — TPM2_SetCommandCodeAuditStatus Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SetCommandCodeAuditStatus {NV}
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_ENDORSEMENT or
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_ALG_HASH+
+
+auditAlg
+
+hash algorithm for the audit digest; if
+TPM_ALG_NULL, then the hash is not changed
+
+TPML_CC
+
+setList
+
+list of commands that will be added to those that will
+be audited
+
+TPML_CC
+
+clearList
+
+list of commands that will no longer be audited
+
+Table 98 — TPM2_SetCommandCodeAuditStatus Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 197
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+23.2.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+
+#include "InternalRoutines.h"
+#include "SetCommandCodeAuditStatus_fp.h"
+
+TPM_RC
+TPM2_SetCommandCodeAuditStatus(
+SetCommandCodeAuditStatus_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+UINT32
+BOOL
+
+result;
+i;
+changed = FALSE;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+// Update hash algorithm
+if(
+in->auditAlg != TPM_ALG_NULL
+&& in->auditAlg != gp.auditHashAlg)
+{
+// Can't change the algorithm and command list at the same time
+if(in->setList.count != 0 || in->clearList.count != 0)
+return TPM_RC_VALUE + RC_SetCommandCodeAuditStatus_auditAlg;
+// Change the hash algorithm for audit
+gp.auditHashAlg = in->auditAlg;
+// Set the digest size to a unique value that indicates that the digest
+// algorithm has been changed. The size will be cleared to zero in the
+// command audit processing on exit.
+gr.commandAuditDigest.t.size = 1;
+// Save the change of command audit data (this sets g_updateNV so that NV
+// will be updagted on exit.)
+NvWriteReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
+} else {
+// Process set list
+for(i = 0; i < in->setList.count; i++)
+// If change is made in CommandAuditSet, set changed flag
+if(CommandAuditSet(in->setList.commandCodes[i]))
+changed = TRUE;
+// Process clear list
+for(i = 0; i < in->clearList.count; i++)
+// If change is made in CommandAuditClear, set changed flag
+if(CommandAuditClear(in->clearList.commandCodes[i]))
+changed = TRUE;
+// if change was made to command list, update NV
+if(changed)
+// this sets g_updateNV so that NV will be updagted on exit.
+NvWriteReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
+
+Page 198
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+61
+62
+63
+64
+
+Part 3: Commands
+
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 199
+October 31, 2013
+
+ Part 3: Commands
+
+24
+
+Trusted Platform Module Library
+
+Integrity Collection (PCR)
+
+24.1
+
+Introduction
+
+In TPM 1.2, an Event was hashed using SHA-1 and then the 20-octet digest was extended to a PCR
+using TPM_Extend(). This specification allows the use of multiple PCR at a given Index, each using a
+different hash algorithm. Rather than require that the external software generate multiple hashes of the
+Event with each being extended to a different PCR, the Event data may be sent to the TPM for hashing.
+This ensures that the resulting digests will properly reflect the algorithms chosen for the PCR even if the
+calling software is unable to implement the hash algorithm.
+NOTE 1
+
+There is continued support for software hashing of events with TPM2_PCR_Extend().
+
+To support recording of an Event that is larger than the TPM input buffer, the caller may use the
+command sequence described in clause 1.
+Change to a PCR requires authorization. The authorization may be with either an authorization value or
+an authorization policy. The platform-specific specifications determine which PCR may be controlled by
+policy. All other PCR are controlled by authorization.
+If a PCR may be associated with a policy, then the algorithm ID of that policy determines whether the
+policy is to be applied. If the algorithm ID is not TPM_ALG_NULL, then the policy digest associated with
+the PCR must match the policySession→policyDigest in a policy session. If the algorithm ID is
+TPM_ALG_NULL, then no policy is present and the authorization requires an EmptyAuth.
+If a platform-specific specification indicates that PCR are grouped, then all the PCR in the group use the
+same authorization policy or authorization value.
+PcrUpdateCounter counter will be incremented on the successful completion of any command that
+modifies (Extends or resets) a PCR unless the platform-specific specification explicitly excludes the PCR
+from being counted.
+NOTE 2
+
+If a command causes PCR in multiple banks to change, the PCR Update Counter may be
+incremented either once or once for each bank.
+
+A platform-specific specification may designate a set of PCR that are under control of the TCB. These
+PCR may not be modified without the proper authorization. Updates of these PCR shall not cause the
+PCR Update Counter to increment.
+EXAMPLE
+
+Updates of the TCB PCR will not cause the PCR update counter to increment b ecause these PCR
+are changed at the whim of the TCB and are not intended to represent the trust state of the platform.
+
+Page 200
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.2
+
+Part 3: Commands
+
+TPM2_PCR_Extend
+
+24.2.1 General Description
+This command is used to cause an update to the indicated PCR. The digests parameter contains one or
+more tagged digest value identified by an algorithm ID. For each digest, the PCR associated with
+pcrHandle is Extended into the bank identified by the tag (hashAlg).
+EXAMPLE
+
+A SHA1 digest would be Extended into the SHA1 bank and a SHA256 digest would be Extended into
+a SHA256 bank.
+
+For each list entry, the TPM will check to see if pcrNum is implemented for that algorithm. If so, the TPM
+shall perform the following operation:
+
+PCR.digestnew [pcrNum][alg] ≔ Halg(PCR.digestold [pcrNum][alg] || data[alg].buffer))
+
+(6)
+
+where
+
+Halg()
+
+hash function using the hash algorithm associated with the PCR
+instance
+
+PCR.digest
+
+the digest value in a PCR
+
+pcrNum
+
+the PCR numeric
+TPM_RH_PCR0)
+
+alg
+
+the PCR algorithm selector for the digest
+
+data[alg].buffer
+
+the bank-specific data to be extended
+
+selector
+
+(equal
+
+to
+
+pcrHandle
+
+–
+
+If no digest value is specified for a bank, then the PCR in that bank are not modified.
+NOTE 1
+
+This allows consistent operation of the digests list for all of the Event recording commands.
+
+If a digest is present and the PCR in that bank is not implemented, the digest value is not used.
+NOTE 2
+
+If the caller includes digests for algorithms that are not implemented, then the TPM will fail the call
+because the unmarshalling of digests will fail. Each of the entries in the list is a TPMT_HA which is a
+hash algorithm followed by a digest. If the algorithm is not implemented, unmarshalling of the
+hashAlg will fail and the TPM will return TPM_RC_HASH.
+
+If the TPM unmarshals the hashAlg of a list entry and the unmarshaled value is not a hash algorithm
+implemented on the TPM, the TPM shall return TPM_RC_HASH.
+The pcrHandle parameter is allowed to reference TPM_RH_NULL. If so, the input parameters are
+processed but no action is taken by the TPM.
+NOTE 3
+
+This command allows a list of digests so that PCR in all banks may be updated in a single
+command. While the semantics of this command allow multiple extends to a single PCR bank, this is
+not the preferred use and the limit on the number of entries in the list make this use somewhat
+impractical.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 201
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.2.2 Command and Response
+Table 99 — TPM2_PCR_Extend Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Extend {NV}
+
+TPMI_DH_PCR+
+
+@pcrHandle
+
+handle of the PCR
+Auth Handle: 1
+Auth Role: USER
+
+TPML_DIGEST_VALUES
+
+digests
+
+list of tagged digest values to be extended
+
+Table 100 — TPM2_PCR_Extend Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 202
+October 31, 2013
+
+.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_Extend_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+current command locality is not allowed to extend the PCR
+referenced by pcrHandle
+
+TPM_RC
+TPM2_PCR_Extend(
+PCR_Extend_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+UINT32
+
+result;
+i;
+
+// Input Validation
+//
+//
+//
+//
+//
+//
+//
+
+NOTE: This function assumes that the unmarshaling function for 'digests' will
+have validated that all of the indicated hash algorithms are valid. If the
+hash algorithms are correct, the unmarshaling code will unmarshal a digest
+of the size indicated by the hash algorithm. If the overall size is not
+consistent, the unmarshaling code will run out of input data or have input
+data left over. In either case, it will cause an unmarshaling error and this
+function will not be called.
+
+// For NULL handle, do nothing and return success
+if(in->pcrHandle == TPM_RH_NULL)
+return TPM_RC_SUCCESS;
+// Check if the extend operation is allowed by the current command locality
+if(!PCRIsExtendAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// If PCR is state saved and we need to update orderlyState, check NV
+// availability
+if(PCRIsStateSaved(in->pcrHandle) && gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+// Internal Data Update
+// Iterate input digest list to extend
+for(i = 0; i < in->digests.count; i++)
+{
+PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg,
+CryptGetHashDigestSize(in->digests.digests[i].hashAlg),
+(BYTE *) &in->digests.digests[i].digest);
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 203
+October 31, 2013
+
+ Part 3: Commands
+
+24.3
+
+Trusted Platform Module Library
+
+TPM2_PCR_Event
+
+24.3.1 General Description
+This command is used to cause an update to the indicated PCR.
+The data in eventData is hashed using the hash algorithm associated with each bank in which the
+indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
+references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
+TPM2_PCR_Extend().
+A TPM shall support an Event.size of zero through 1,024 inclusive (Event.size is an octet count). An
+Event.size of zero indicates that there is no data but the indicated operations will still occur,
+EXAMPLE 1
+
+If the command implements PCR[2] in a SHA1 bank and a SHA256 bank, then an extend to PCR[2]
+will cause eventData to be hashed twice, once with SHA1 and once with SHA256. The SHA1 hash of
+eventData will be Extended to PCR[2] in the SHA1 bank and the SHA256 hash of eventData will be
+Extended to PCR[2] of the SHA256 bank.
+
+On successful command completion, digests will contain the list of tagged digests of eventData that was
+computed in preparation for extending the data into the PCR. At the option of the TPM, the list may
+contain a digest for each bank, or it may only contain a digest for each bank in which pcrHandle is extant.
+EXAMPLE 2
+
+Assume a TPM that implements a SHA1 bank and a SHA256 bank and that PCR[22] is only
+implemented in the SHA1 bank. If pcrHandle references PCR[22], then digests may contain either a
+SHA1 and a SHA256 digest or just a SHA1 digest.
+
+Page 204
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.3.2 Command and Response
+Table 101 — TPM2_PCR_Event Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Event {NV}
+
+TPMI_DH_PCR+
+
+@pcrHandle
+
+Handle of the PCR
+Auth Handle: 1
+Auth Role: USER
+
+TPM2B_EVENT
+
+eventData
+
+Event data in sized buffer
+
+Table 102 — TPM2_PCR_Event Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPML_DIGEST_VALUES
+
+digests
+
+Family “2.0”
+Level 00 Revision 00.99
+
+.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 205
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_Event_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+current command locality is not allowed to extend the PCR
+referenced by pcrHandle
+
+TPM_RC
+TPM2_PCR_Event(
+PCR_Event_In
+PCR_Event_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+HASH_STATE
+UINT32
+UINT16
+
+result;
+hashState;
+i;
+size;
+
+// Input Validation
+// If a PCR extend is required
+if(in->pcrHandle != TPM_RH_NULL)
+{
+// If the PCR is not allow to extend, return error
+if(!PCRIsExtendAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// If PCR is state saved and we need to update orderlyState, check NV
+// availability
+if(PCRIsStateSaved(in->pcrHandle) && gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+}
+// Internal Data Update
+out->digests.count = HASH_COUNT;
+// Iterate supported PCR bank algorithms to extend
+for(i = 0; i < HASH_COUNT; i++)
+{
+TPM_ALG_ID hash = CryptGetHashAlgByIndex(i);
+out->digests.digests[i].hashAlg = hash;
+size = CryptStartHash(hash, &hashState);
+CryptUpdateDigest2B(&hashState, &in->eventData.b);
+CryptCompleteHash(&hashState, size,
+(BYTE *) &out->digests.digests[i].digest);
+if(in->pcrHandle != TPM_RH_NULL)
+PCRExtend(in->pcrHandle, hash, size,
+(BYTE *) &out->digests.digests[i].digest);
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 206
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.4
+
+Part 3: Commands
+
+TPM2_PCR_Read
+
+24.4.1 General Description
+This command returns the values of all PCR specified in pcrSelect.
+The TPM will process the list of TPMS_PCR_SELECTION in pcrSelectionIn in order. Within each
+TPMS_PCR_SELECTION, the TPM will process the bits in the pcrSelect array in ascending PCR order
+(see Part 2 for definition of the PCR order). If a bit is SET, and the indicated PCR is present, then the
+TPM will add the digest of the PCR to the list of values to be returned in pcrValue.
+The TPM will continue processing bits until all have been processed or until pcrValues would be too large
+to fit into the output buffer if additional values were added.
+The returned pcrSelectionOut will have a bit SET in its pcrSelect structures for each value present in
+pcrValues.
+The current value of the PCR Update Counter is returned in pcrUpdateCounter.
+The returned list may be empty if none of the selected PCR are implemented.
+NOTE
+
+If no PCR are returned from a bank, the selector for the bank will be present in pcrSelectionOut.
+
+No authorization is required to read a PCR and any implemented PCR may be read from any locality.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 207
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.4.2 Command and Response
+Table 103 — TPM2_PCR_Read Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Read
+
+TPML_PCR_SELECTION
+
+pcrSelectionIn
+
+The selection of PCR to read
+
+Table 104 — TPM2_PCR_Read Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+UINT32
+
+pcrUpdateCounter
+
+the current value of the PCR update counter
+
+TPML_PCR_SELECTION
+
+pcrSelectionOut
+
+the PCR in the returned list
+
+TPML_DIGEST
+
+pcrValues
+
+the contents of the PCR indicated in pcrSelect as
+tagged digests
+
+Page 208
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.4.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+
+#include "InternalRoutines.h"
+#include "PCR_Read_fp.h"
+
+TPM_RC
+TPM2_PCR_Read(
+PCR_Read_In
+PCR_Read_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Call PCR read function. input pcrSelectionIn parameter could be changed
+// to reflect the actual PCR being returned
+PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter);
+out->pcrSelectionOut = in->pcrSelectionIn;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 209
+October 31, 2013
+
+ Part 3: Commands
+
+24.5
+
+Trusted Platform Module Library
+
+TPM2_PCR_Allocate
+
+24.5.1 General Description
+This command is used to set the desired PCR allocation of PCR and algorithms. This command requires
+platformAuth.
+The TPM will evaluate the request and, if sufficient memory is available for the requested allocation, the
+TPM will store the allocation request for use during the next TPM2_Startup(TPM_SU_CLEAR) operation.
+The PCR allocation in place when this command is executed will be retained until the next
+TPM2_Startup(TPM_SU_CLEAR).
+If no allocation is specified for a bank, then no PCR will be allocated to that bank. If a bank is listed more
+than once, then the last selection in the pcrAllocation list is the one that the TPM will attempt to allocate.
+This command shall not allocate more PCR in any bank than there are PCR attribute definitions. The
+PCR attribute definitions indicate how a PCR is to be managed – if it is resettable, the locality for update,
+etc. In the response to this command, the TPM returns the maximum number of PCR allowed for any
+bank.
+If the command is properly authorized, it will return SUCCESS even though the request fails. This is to
+allow the TPM to return information about the size needed for the requested allocation and the size
+available. If the sizeNeeded parameter in the return is less than or equal to the sizeAvailable parameter,
+then the allocationSuccess parameter will be YES.
+After this command, TPM2_Shutdown() is only allowed to have a startupType equal to TPM_SU_CLEAR.
+NOTE
+
+Even if this command does not cause the PCR allocation to change, the TPM cannot have its state
+saved. This is done in order to simplify the implementation. There is no need to optimize this
+command as it is not expected to be used more than once in the lifetime of the TPM (it can be used
+any number of times but there is no justification for optimization) .
+
+Page 210
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.5.2 Command and Response
+Table 105 — TPM2_PCR_Allocate Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Allocate {NV}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPML_PCR_SELECTION
+
+pcrAllocation
+
+the requested allocation
+
+Table 106 — TPM2_PCR_Allocate Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_YES_NO
+
+allocationSuccess
+
+YES if the allocation succeeded
+
+UINT32
+
+maxPCR
+
+maximum number of PCR that may be in a bank
+
+UINT32
+
+sizeNeeded
+
+number of octets required to satisfy the request
+
+UINT32
+
+sizeAvailable
+
+Number of octets available. Computed before the
+allocation.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 211
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.5.3 Detailed Actions
+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
+33
+34
+
+#include "InternalRoutines.h"
+#include "PCR_Allocate_fp.h"
+
+TPM_RC
+TPM2_PCR_Allocate(
+PCR_Allocate_In
+PCR_Allocate_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point.
+// Note: These codes are not listed in the return values above because it is
+// an implementation choice to check in this routine rather than in a common
+// function that is called before these actions are called. These return values
+// are described in the Response Code section of Part 3.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Command Output
+// Call PCR Allocation function.
+out->allocationSuccess = PCRAllocate(&in->pcrAllocation, &out->maxPCR,
+&out->sizeNeeded, &out->sizeAvailable);
+// if re-configuration succeeds, set the flag to indicate PCR configuration is
+// going to be changed in next boot
+if(out->allocationSuccess == YES)
+g_pcrReConfig = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 212
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.6
+
+Part 3: Commands
+
+TPM2_PCR_SetAuthPolicy
+
+24.6.1 General Description
+This command is used to associate a policy with a PCR or group of PCR. The policy determines the
+conditions under which a PCR may be extended or reset.
+A policy may only be associated with a PCR that has been defined by a platform-specific specification as
+allowing a policy. If the TPM implementation does not allow a policy for pcrNum, the TPM shall return
+TPM_RC_VALUE.
+A platform-specific specification may group PCR so that they share a common policy. In such case, a
+pcrNum that selects any of the PCR in the group will change the policy for all PCR in the group.
+The policy setting is persistent and may only be changed by TPM2_PCR_SetAuthPolicy() or by
+TPM2_ChangePPS().
+Before this command is first executed on a TPM or after TPM2_ChangePPS(), the access control on the
+PCR will be set to the default value defined in the platform-specific specification.
+NOTE 1
+
+It is expected that the typical default will be with the policy hash set to TPM_ALG_NULL and an
+Empty Buffer for the authPolicy value. This will allow an EmptyAuth to be used as the authorization
+value.
+
+If the size of the data buffer in authPolicy is not the size of a digest produced by hashAlg, the TPM shall
+return TPM_RC_SIZE.
+NOTE 2
+
+If hashAlg is TPM_ALG_NULL, then the size is required to be zero.
+
+This command requires platformAuth/platformPolicy.
+NOTE 3
+
+If the PCR is in multiple policy sets, the policy will be changed in only one set. The set that is
+changed will be implementation dependent.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 213
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.6.2 Command and Response
+Table 107 — TPM2_PCR_SetAuthPolicy Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_SetAuthPolicy {NV}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+authPolicy
+
+the desired authPolicy
+
+TPMI_ALG_HASH+
+
+policyDigest
+
+the digest of the policy
+
+TPMI_DH_PCR
+
+pcrNum
+
+the PCR for which the policy is to be set
+
+Table 108 — TPM2_PCR_SetAuthPolicy Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 214
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.6.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_SetAuthPolicy_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+size of authPolicy is not the size of a digest produced by policyDigest
+
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+
+Meaning
+
+PCR referenced by pcrNum is not a member of a PCR policy group
+
+TPM_RC
+TPM2_PCR_SetAuthPolicy(
+PCR_SetAuthPolicy_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+
+groupIndex;
+
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation:
+// Check the authPolicy consistent with hash algorithm
+if(in->authPolicy.t.size != CryptGetHashDigestSize(in->policyDigest))
+return TPM_RC_SIZE + RC_PCR_SetAuthPolicy_authPolicy;
+// If PCR does not belong to a policy group, return TPM_RC_VALUE
+if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex))
+return TPM_RC_VALUE + RC_PCR_SetAuthPolicy_pcrNum;
+// Internal Data Update
+// Set PCR policy
+gp.pcrPolicies.hashAlg[groupIndex] = in->policyDigest;
+gp.pcrPolicies.policy[groupIndex] = in->authPolicy;
+// Save new policy to NV
+NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 215
+October 31, 2013
+
+ Part 3: Commands
+
+24.7
+
+Trusted Platform Module Library
+
+TPM2_PCR_SetAuthValue
+
+24.7.1 General Description
+This command changes the authValue of a PCR or group of PCR.
+An authValue may only be associated with a PCR that has been defined by a platform-specific
+specification as allowing an authorization value. If the TPM implementation does not allow an
+authorization for pcrNum, the TPM shall return TPM_RC_VALUE. A platform-specific specification may
+group PCR so that they share a common authorization value. In such case, a pcrNum that selects any of
+the PCR in the group will change the authValue value for all PCR in the group.
+The authorization setting is set to EmptyAuth on each STARTUP(CLEAR) or by TPM2_Clear(). The
+authorization setting is preserved by SHUTDOWN(STATE).
+
+Page 216
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.7.2 Command and Response
+Table 109 — TPM2_PCR_SetAuthValue Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_SetAuthValue
+
+TPMI_DH_PCR
+
+@pcrHandle
+
+handle for a PCR that may have an authorization value
+set
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+auth
+
+the desired authorization value
+
+Table 110 — TPM2_PCR_SetAuthValue Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 217
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_SetAuthValue_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+
+Meaning
+PCR referenced by pcrHandle is not a member of a PCR
+authorization group
+
+TPM_RC
+TPM2_PCR_SetAuthValue(
+PCR_SetAuthValue_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+TPM_RC
+
+groupIndex;
+result;
+
+// Input Validation:
+// If PCR does not belong to an auth group, return TPM_RC_VALUE
+if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex))
+return TPM_RC_VALUE;
+// The command may cause the orderlyState to be cleared due to the update of
+// state clear data. If this is the case, Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+g_clearOrderly = TRUE;
+}
+// Internal Data Update
+// Set PCR authValue
+gc.pcrAuthValues.auth[groupIndex] = in->auth;
+return TPM_RC_SUCCESS;
+}
+
+Page 218
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.8
+
+Part 3: Commands
+
+TPM2_PCR_Reset
+
+24.8.1 General Description
+If the attribute of a PCR allows the PCR to be reset and proper authorization is provided, then this
+command may be used to set the PCR to zero. The attributes of the PCR may restrict the locality that can
+perform the reset operation.
+NOTE 1
+
+The definition of TPMI_DH_PCR in Part 2 indicates that if pcrHandle is out of the allowed range for
+PCR, then the appropriate return value is TPM_RC_VALUE.
+
+If pcrHandle references a PCR that cannot be reset, the TPM shall return TPM_RC_LOCALITY.
+NOTE 2
+
+TPM_RC_LOCALITY is returned because the reset attributes are defined on a per -locality basis.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 219
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.8.2 Command and Response
+Table 111 — TPM2_PCR_Reset Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PCR_Reset {NV}
+
+TPMI_DH_PCR
+
+@pcrHandle
+
+the PCR to reset
+Auth Index: 1
+Auth Role: USER
+
+Table 112 — TPM2_PCR_Reset Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 220
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.8.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PCR_Reset_fp.h"
+Error Returns
+TPM_RC_LOCALITY
+
+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
+33
+34
+35
+36
+
+Meaning
+current command locality is not allowed to reset the PCR referenced
+by pcrHandle
+
+TPM_RC
+TPM2_PCR_Reset(
+PCR_Reset_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input Validation
+// Check if the reset operation is allowed by the current command locality
+if(!PCRIsResetAllowed(in->pcrHandle))
+return TPM_RC_LOCALITY;
+// If PCR is state saved and we need to update orderlyState, check NV
+// availability
+if(PCRIsStateSaved(in->pcrHandle) && gp.orderlyState != SHUTDOWN_NONE)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+g_clearOrderly = TRUE;
+}
+// Internal Data Update
+// Reset seleccted PCR in all banks to 0
+PCRSetValue(in->pcrHandle, 0);
+// Indicate that the PCR changed so that pcrCounter will be incremented if
+// necessary.
+PCRChanged(in->pcrHandle);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 221
+October 31, 2013
+
+ Part 3: Commands
+
+24.9
+
+Trusted Platform Module Library
+
+_TPM_Hash_Start
+
+24.9.1 Description
+This indication from the TPM interface indicates the start of a dynamic Core Root of Trust for
+Measurement (D-CRTM) measurement sequence. On receipt of this indication, the TPM will initialize an
+Event sequence context.
+If no object memory is available for creation of the sequence context, the TPM will flush the context of an
+object so that creation of the Event sequence context will always succeed.
+A platform-specific specification may allow this indication before TPM2_Startup().
+NOTE
+
+If this indication occurs after TPM2_Startup(), it is the responsibility of software to ensure that an
+object context slot is available or to deal with the consequences of having the TPM select an
+arbitrary object to be flushed. If this indication occurs before TPM2_Startup() then all context slots
+are available.
+
+Page 222
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+24.9.2 Detailed Actions
+1
+
+#include "InternalRoutines.h"
+
+This function is called to process a _TPM_Hash_Start() indication.
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+void
+_TPM_Hash_Start(void)
+{
+TPM_RC
+TPMI_DH_OBJECT
+
+result;
+handle;
+
+// If a DRTM sequence object exists, terminate it.
+if(g_DRTMHandle != TPM_RH_UNASSIGNED)
+ObjectTerminateEvent();
+// Create an event sequence object and store the handle in global
+// g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point
+// The null value for the 'auth' parameter will cause the sequence structure to
+// be allocated without being set as present. This keeps the sequence from
+// being left behind if the sequence is terminated early.
+result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
+// If a free slot was not available, then free up a slot.
+if(result != TPM_RC_SUCCESS)
+{
+// An implementation does not need to have a fixed relationship between
+// slot numbers and handle numbers. To handle the general case, scan for
+// a handle that is assigned an free it for the DRTM sequence.
+// In the reference implementation, the relationship between handles and
+// slots is fixed. So, if the call to ObjectCreateEvenSequence()
+// failed indicating that all slots are occupied, then the first handle we
+// are going to check (TRANSIENT_FIRST) will be occupied. It will be freed
+// so that it can be assigned for use as the DRTM sequence object.
+for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++)
+{
+// try to flush the first object
+if(ObjectIsPresent(handle))
+break;
+}
+// If the first call to find a slot fails but none of the slots is occupied
+// then there's a big problem
+pAssert(handle < TRANSIENT_LAST);
+// Free the slot
+ObjectFlush(handle);
+// Try to create an event sequence object again. This time, we must
+// succeed.
+result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
+pAssert(result == TPM_RC_SUCCESS);
+}
+return;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 223
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.10 _TPM_Hash_Data
+24.10.1
+
+Description
+
+This indication from the TPM interface indicates arrival of one or more octets of data that are to be
+included in the Core Root of Trust for Measurement (CRTM) sequence context created by the
+_TPM_Hash_Start indication. The context holds data for each hash algorithm for each PCR bank
+implemented on the TPM.
+If no DRTM Event Sequence context exists, this indication is discarded and no other action is performed.
+
+Page 224
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.10.2
+1
+2
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "Platform.h"
+
+This function is called to process a _TPM_Hash_Data() indication.
+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
+
+void
+_TPM_Hash_Data(
+UINT32
+BYTE
+
+dataSize,
+*data
+
+UINT32
+HASH_OBJECT
+
+// IN: size of data to be extend
+// IN: data buffer
+
+i;
+*hashObject;
+
+)
+{
+
+// If there is no DRTM sequence object, then _TPM_Hash_Start
+// was not called so this function returns without doing
+// anything.
+if(g_DRTMHandle == TPM_RH_UNASSIGNED)
+return;
+hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
+pAssert(hashObject->attributes.eventSeq);
+// For each of the implemented hash algorithms, update the digest with the
+// data provided. NOTE: the implementation could be done such that the TPM
+// only computes the hash for the banks that contain the DRTM PCR.
+for(i = 0; i < HASH_COUNT; i++)
+{
+// Update sequence object
+CryptUpdateDigest(&hashObject->state.hashState[i], dataSize, data);
+}
+return;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 225
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+24.11 _TPM_Hash_End
+24.11.1
+
+Description
+
+This indication from the TPM interface indicates the end of the CRTM measurement. This indication is
+discarded and no other action performed if the TPM does not contain a CRTM Event sequence context.
+NOTE
+
+A CRTM Event Sequence context is created by _TPM_Hash_Start().
+
+If the CRTM Event sequence occurs after TPM2_Startup(), the TPM will set all of the PCR designated in
+the platform-specific specifications as resettable by this event to the value indicated in the platform
+specific specification, and increment restartCount. The TPM will then Extend the Event Sequence
+digest/digests into the designated, DRTM PCR.
+PCR[DRTM][hashAlg] ≔ HhashAlg (initial_value || HhashAlg (hash_data))
+
+(7)
+
+where
+DRTM
+
+index for CRTM PCR designated by a platform-specific
+specification
+
+hashAlg
+
+hash algorithm associated with a bank of PCR
+
+initial_value
+
+initialization value specified in the platform-specific specification
+(should be 0…0)
+
+hash_data
+
+all the octets of data received in _TPM_Hash_Data indications
+
+A _TPM_Hash_End indication that occurs after TPM2_Startup() will increment pcrUpdateCounter unless
+a platform-specific specification excludes modifications of PCR[DRTM] from causing an increment.
+A platform-specific specification may allow an H-CRTM Event Sequence before TPM2_Startup(). If so,
+_TPM_Hash_End will complete the digest, initialize PCR[0] with a digest-size value of 4, and then extend
+the H-CRTM Event Sequence data into PCR[0].
+PCR[0][hashAlg] ≔ HhashAlg (0…04 || HhashAlg (hash_data))
+NOTE
+
+(8)
+
+The entire sequence of _TPM_Hash_Start, _TPM_Hash_Data, and _TPM_Hash_End are required to
+complete before TPM2_Startup() or the sequence will have no effect on the TPM.
+
+Page 226
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+24.11.2
+1
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+
+This function is called to process a _TPM_Hash_End() indication.
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+
+void
+_TPM_Hash_End(void)
+{
+UINT32
+TPM2B_DIGEST
+HASH_OBJECT
+TPMI_DH_PCR
+
+i;
+digest;
+*hashObject;
+pcrHandle;
+
+// If the DRTM handle is not being used, then either _TPM_Hash_Start has not
+// been called, _TPM_Hash_End was previously called, or some other command
+// was executed and the sequence was aborted.
+if(g_DRTMHandle == TPM_RH_UNASSIGNED)
+return;
+// Get DRTM sequence object
+hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
+// Is this _TPM_Hash_End after Startup or before
+if(TPMIsStarted())
+{
+// After
+// Reset the DRTM PCR
+PCRResetDynamics();
+// Extend the DRTM_PCR.
+pcrHandle = PCR_FIRST + DRTM_PCR;
+// DRTM sequence increments restartCount
+gr.restartCount++;
+}
+else
+{
+pcrHandle = PCR_FIRST + HCRTM_PCR;
+}
+// Complete hash and extend PCR, or if this is an HCRTM, complete
+// the hash and write the PCR
+for(i = 0; i < HASH_COUNT; i++)
+{
+TPMI_ALG_HASH
+hash = CryptGetHashAlgByIndex(i);
+// Complete hash
+digest.t.size = CryptGetHashDigestSize(hash);
+CryptCompleteHash2B(&hashObject->state.hashState[i], &digest.b);
+// If this is DRTM, extend to zeroed PCR
+// If this is H-DRTM, copy to HCRM PCR
+if(TPMIsStarted())
+// Extend PCR
+PCRExtend(pcrHandle, hash, digest.t.size, digest.t.buffer);
+else
+PcrWrite(pcrHandle, hash, &digest);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 227
+October 31, 2013
+
+ Part 3: Commands
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+
+Trusted Platform Module Library
+
+}
+// Flush sequence object.
+ObjectFlush(g_DRTMHandle);
+g_DRTMHandle = TPM_RH_UNASSIGNED;
+g_DrtmPreStartup = TRUE;
+return;
+}
+
+Page 228
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25
+
+Part 3: Commands
+
+Enhanced Authorization (EA) Commands
+
+25.1
+
+Introduction
+
+The commands in this clause 1 are used for policy evaluation. When successful, each command will
+update the policySession→policyDigest in a policy session context in order to establish that the
+authorizations required to use an object have been provided. Many of the commands will also modify
+other parts of a policy context so that the caller may constrain the scope of the authorization that is
+provided.
+NOTE 1
+
+Many of the terms used in this clause are described in detail i n Part 1 and are not redefined in this
+clause.
+
+The policySession parameter of the command is the handle of the policy session context to be modified
+by the command.
+If the policySession parameter indicates a trial policy session, then the policySession→policyDigest will
+be updated and the indicated validations are not performed.
+NOTE 2
+
+A policy session is a trial policy by TPM2_StartAuthSession( sessionType = TPM_SE_TRIAL).
+
+NOTE 3
+
+Unless there is an unmarshaling error in the parameters of the command, these commands will
+return TPM_RC_SUCCESS when policySession references a trial session.
+
+NOTE 4
+
+Policy context other than the policySession→policyDigest may be updated for a trial policy but it is
+not required.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 229
+October 31, 2013
+
+ Part 3: Commands
+
+25.2
+
+Trusted Platform Module Library
+
+Signed Authorization Actions
+
+25.2.1 Introduction
+The TPM2_PolicySigned, TPM_PolicySecret, and TPM2_PolicyTicket commands use many of the same
+functions. This clause consolidates those functions to simplify the document and to ensure uniformity of
+the operations.
+25.2.2 Policy Parameter Checks
+These parameter checks will be performed when indicated in the description of each of the commands:
+a) nonceTPM – If this parameter is not the Empty Buffer, and
+policySession→nonceTPM, then the TPM shall return TPM_RC_VALUE.
+
+it
+
+does
+
+not
+
+match
+
+b) expiration – If this parameter is not zero, then its absolute value is compared to the time in seconds
+since the policySession→nonceTPM was generated. If more time has passed than indicted in
+expiration, the TPM shall return TPM_RC_EXPIRED. If nonceTPM is the Empty buffer, and expiration
+is non-zero, then the TPM shall return TPM_RC_EXPIRED.
+c) timeout – This parameter is compared to the current TPM time. If policySession→timeout is in the
+past, then the TPM shall return TPM_RC_EXPIRED.
+NOTE 1
+
+The expiration parameter is present in the TPM2_PolicySigned and TPM2_PolicySecret
+command and timeout is the analogous parameter in the TPM2_PolicyTicket command.
+
+d) cpHashA – If this parameter is not an Empty Buffer
+NOTE 2
+
+CpHashA is the hash of the command to be executed using this policy session in the
+authorization. The algorithm used to compute this hash is required to be the algorithm of the
+policy session.
+
+1) the TPM shall return TPM_RC_CPHASH if policySession→cpHash does not have its default
+value or the contents of policySession→cpHash are not the same as cpHashA; or
+NOTE 3
+
+CpHash is the expected cpHash value held in the policy session context.
+
+2) the TPM shall return TPM_RC_SIZE
+policySession→policyDigest.
+NOTE 4
+
+Page 230
+October 31, 2013
+
+if
+
+cpHashA
+
+is
+
+not
+
+the
+
+same
+
+size
+
+as
+
+PolicySession→policyDigest is the size of the digest produced by the hash algorithm used to
+compute policyDigest.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.2.3 PolicyDigest Update Function (PolicyUpdate())
+This is the update process for policySession→policyDigest used by TPM2_PolicySigned(),
+TPM2_PolicySecret(), TPM2_PolicyTicket(), and TPM2_PolicyAuthorize(). The function prototype for the
+update function is:
+
+PolicyUpdate(commandCode, arg2, arg3)
+
+(9)
+
+where
+
+arg2
+
+a TPM2B_NAME
+
+arg3
+
+a TPM2B
+
+These parameters are used to update policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || commandCode || arg2.name)
+
+(10)
+
+policyDigestnew+1 ≔ HpolicyAlg(policyDigestnew || arg3.buffer)
+
+(11)
+
+followed by
+
+where
+
+HpolicyAlg()
+
+the hash algorithm chosen when the policy session was started
+
+NOTE 1
+
+If arg3 is a TPM2B_NAME, then arg3.buffer will actually be an arg3.name.
+
+NOTE 2
+
+The arg2.size and arg3.size fields are not included in the hashes.
+
+NOTE 3
+
+PolicyUpdate() uses two hashes because arg2 and arg3 are variable-sized and the concatenation of
+arg2 and arg3 in a single hash could produce the same digest even though arg2 and arg3 are
+different. Processing of the arguments separately in different Extend operation insures that the
+digest produced by PolicyUpdate() will be different if arg2 and arg3 are different.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 231
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.2.4 Policy Context Updates
+When a policy command modifies some part of the policy session context other than the
+policySession→policyDigest, the following rules apply.
+
+
+cpHash – this parameter may only be changed if it contains its initialization value (an Empty String).
+If cpHash is not the Empty String when a policy command attempts to update it, the TPM will return
+an error (TPM_RC_CPHASH) if the current and update values are not the same.
+
+
+
+timeOut – this parameter may only be changed to a smaller value. If a command attempts to update
+this value with a larger value (longer into the future), the TPM will discard the update value. This is
+not an error condition.
+
+
+
+commandCode – once set by a policy command, this value may not be change except by
+TPM2_PolicyRestart(). If a policy command tries to change this to a different value, an error is
+returned (TPM_RC_POLICY_CC).
+
+
+
+pcrUpdateCounter – this parameter is updated by TPM2_PolicyPCR(). This value may only be set
+once during a policy. Each time TPM2_PolicyPCR() executes, it checks to see if
+policySession→pcrUpdateCounter has its default state indicating that this is the first
+TPM2_PolicyPCR(). If it has its default value, then policySession→pcrUpdateCounter is set to the
+current value of pcrUpdateCounter. If policySession→pcrUpdateCounter does not have its default
+value and its value is not the same as pcrUpdateCounter, the TPM shall return
+TPM_RC_PCR_CHANGED.
+NOTE
+
+If this parameter and pcrUpdateCounter are not the same, it indicates that PCR have changed
+since checked by the previous TPM2_PolicyPCR(). Since they have changed, the previous PCR
+validation is no longer valid.
+
+
+
+commandLocality – this parameter is the logical AND of all enabled localities. All localities are
+enabled for a policy when the policy session is created. TPM2_PolicyLocalities() selectively disables
+localities. Once use of a policy for a locality has been disabled, it cannot be enabled except by
+TPM2_PolicyRestart().
+
+
+
+isPPRequired – once SET, this parameter may only be CLEARed by TPM2_PolicyRestart().
+
+
+
+isAuthValueNeeded – once SET, this parameter may only be CLEARed by TPM2_PolicyPassword()
+or TPM2_PolicyRestart().
+
+
+
+isPasswordNeeded – once SET, this parameter may only be CLEARed by TPM2_PolicyAuthValue()
+or TPM2_PolicyRestart(),
+
+NOTE
+
+Both TPM2_PolicyAuthValue() and TPM2_PolicyPassword() change policySession→policyDigest in
+the same way. The different commands simply indicate to the TPM the format used for the authValue
+(HMAC or clear text). Both commands could be in the same policy. The final instance of these
+commands determines the format.
+
+Page 232
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.2.5 Policy Ticket Creation
+If for TPM2_PolicySigned() or TPM2_PolicySecret() the caller specified a negative value for expiration,
+and the policy update succeeds, then the TPM will return a ticket that includes a value indicating when
+the authorization expires. The required computation for the digest in the authorization ticket is:
+
+HMAC(proof, HpolicyAlg(ticketType || timeout || cpHashA || policyRef || authObject→Name)) (12)
+where
+
+proof
+
+secret associated with the storage primary seed (SPS) of the
+TPM
+
+HpolicyAlg
+
+hash function using the hash algorithm associated with the policy
+session
+
+ticketType
+
+either TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED,
+used to indicate type of the ticket
+
+NOTE 1
+
+If
+the
+ticket
+is
+produced
+by
+TPM2_PolicySecret()
+then
+ticketType
+is
+TPM_ST_AUTH_SECRET and if produced by TPM2_PolicySigned() then ticketType is
+TPM_ST_AUTH_SIGNED.
+
+timeout
+
+NOTE 2
+
+implementation-specific representation of the expiration time of
+the ticket; required to be the implementation equivalent of
+policySession→startTime plus the absolute value of expiration
+Timeout is not the same as expiration. The expiration value in the aHash is a relative time,
+using the creation time of the authorization session (TPM2_StartAuthSession()) as its
+reference. The timeout parameter is an absolute time, using TPM Clock as the reference.
+
+cpHashA
+
+the command parameter digest for the command being
+authorized; computed using the hash algorithm of the policy
+session
+
+policyRef
+
+the commands that use this function have a policyRef parameter
+and the value of that parameter is used here
+
+authObject→Name
+
+Name associated with the authObject parameter
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 233
+October 31, 2013
+
+ Part 3: Commands
+25.3
+
+Trusted Platform Module Library
+
+TPM2_PolicySigned
+
+25.3.1 General Description
+This command includes a signed authorization in a policy. The command ties the policy to a signing key
+by including the Name of the signing key in the policyDigest
+If policySession is a trial session, the TPM will not check the signature and will update
+policySession→policyDigest as described in 25.2.3 as if a properly signed authorization was received; but
+no ticket will be produced.
+If policySession is not a trial session, the TPM will validate auth and only perform the update if it is a valid
+signature over the fields of the command.
+The authorizing object will sign a digest of the authorization qualifiers: nonceTPM, expiration, cpHashA,
+and policyRef. The digest is computed as:
+
+aHash ≔ HauthAlg(nonceTPM || expiration || cpHashA || policyRef)
+
+(13)
+
+where
+
+HauthAlg()
+NOTE 1
+
+the hash associated with the auth parameter of this command
+Each signature and key combination indicates the scheme and each scheme has an
+associated hash.
+
+nonceTPM
+
+the nonceTPM parameter from the TPM2_StartAuthSession()
+response. If the authorization is not limited to this session, the
+size of this value is zero.
+
+expiration
+
+time limit on authorization set by authorizing object. This 32-bit
+value is set to zero if the expiration time is not being set.
+
+cpHashA
+
+digest of the command parameters for the command being
+approved using the hash algorithm of the policy session. Set to
+an EmptyAuth if the authorization is not limited to a specific
+command.
+
+NOTE 2
+
+This is not the cpHash of this TPM2_PolicySigned() command.
+
+policyRef
+EXAMPLE
+
+an opaque value determined by the authorizing entity. Set to the
+Empty Buffer if no value is present.
+
+The computation for an aHash if there are no restrictions is:
+
+aHash ≔ HauthAlg(00 00 00 0016)
+which is the hash of an expiration time of zero.
+
+The aHash is signed by the private key associated with key. The signature and signing parameters are
+combined to create the auth parameter.
+The TPM will perform the parameter checks listed in 25.2.2
+If the parameter checks succeed, the TPM will construct a test digest (tHash) over the provided
+parameters using the same formulation a shown in equation (13) above.
+If tHash does not match the digest of the signed aHash, then the authorization fails and the TPM shall
+return TPM_RC_POLICY_FAIL and make no change to policySession→policyDigest.
+
+Page 234
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+When all validations have succeeded, policySession→policyDigest is updated by PolicyUpdate() (see
+25.2.3).
+
+PolicyUpdate(TPM_CC_PolicySigned, authObject→Name, policyRef)
+
+(14)
+
+If the cpHashA parameter is not an Empty Buffer, it is copied to policySession→cpHash.
+The TPM will optionally produce a ticket as described in 25.2.5.
+Authorization to use authObject is not required.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 235
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.3.2 Command and Response
+Table 113 — TPM2_PolicySigned Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicySigned
+
+TPMI_DH_OBJECT
+
+authObject
+
+handle for a public key that will validate the signature
+Auth Index: None
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_NONCE
+
+nonceTPM
+
+the policy nonce for the session
+If the nonce is not included in the authorization
+qualification, this field is the Empty Buffer.
+
+TPM2B_DIGEST
+
+cpHashA
+
+digest of the command parameters to which this
+authorization is limited
+This is not the cpHash for this command but the cpHash
+for the command to which this policy session will be
+applied. If it is not limited, the parameter will be the
+Empty Buffer.
+
+TPM2B_NONCE
+
+policyRef
+
+a reference to a policy relating to the authorization –
+may be the Empty Buffer
+Size is limited to be no larger than the nonce size
+supported on the TPM.
+
+INT32
+
+expiration
+
+time when authorization will expire, measured in
+seconds from the time that nonceTPM was generated
+If expiration is zero, a NULL Ticket is returned.
+
+TPMT_SIGNATURE
+
+auth
+
+signed authorization (not optional)
+
+Description
+
+Table 114 — TPM2_PolicySigned Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_TIMEOUT
+
+timeout
+
+TPMT_TK_AUTH
+
+policyTicket
+
+Page 236
+October 31, 2013
+
+implementation-specific time value, used to indicate to
+the TPM when the ticket expires
+NOTE
+
+If policyTicket is a NULL Ticket, then this shall be
+the Empty Buffer.
+
+produced if the command succeeds and expiration in
+the command was non-zero; this ticket will use the
+TPMT_ST_AUTH_SIGNED structure tag
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "Policy_spt_fp.h"
+#include "PolicySigned_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+cpHash was previously set to a different value
+
+TPM_RC_EXPIRED
+
+expiration indicates a time in the past or expiration is non-zero but no
+nonceTPM is present
+
+TPM_RC_HANDLE
+
+authObject need to have sensitive portion loaded
+
+TPM_RC_KEY
+
+authObject is not a signing scheme
+
+TPM_RC_NONCE
+
+nonceTPM is not the nonce associated with the policySession
+
+TPM_RC_SCHEME
+
+the signing scheme of auth is not supported by the TPM
+
+TPM_RC_SIGNATURE
+
+the signature is not genuine
+
+TPM_RC_SIZE
+
+input cpHash has wrong size
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+
+Meaning
+
+input policyID or expiration does not match the internal data in policy
+session
+
+TPM_RC
+TPM2_PolicySigned(
+PolicySigned_In
+PolicySigned_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+SESSION
+OBJECT
+TPM2B_NAME
+TPM2B_DIGEST
+HASH_STATE
+UINT32
+
+result = TPM_RC_SUCCESS;
+*session;
+*authObject;
+entityName;
+authHash;
+hashState;
+expiration = (in->expiration < 0)
+? -(in->expiration) : in->expiration;
+authTimeout = 0;
+
+)
+{
+
+UINT64
+// Input Validation
+
+// Set up local pointers
+session = SessionGet(in->policySession);
+authObject = ObjectGet(in->authObject);
+
+// the session structure
+// pointer for the object
+//
+providing authorization
+//
+signature
+
+// Only do input validation if this is not a trial policy session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+if(expiration != 0)
+authTimeout = expiration * 1000 + session->startTime;
+result = PolicyParameterChecks(session, authTimeout,
+&in->cpHashA, &in->nonceTPM,
+RC_PolicySigned_nonceTPM,
+RC_PolicySigned_cpHashA,
+RC_PolicySigned_expiration);
+if(result != TPM_RC_SUCCESS)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 237
+October 31, 2013
+
+ Part 3: Commands
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
+Trusted Platform Module Library
+
+return result;
+// Re-compute the digest being signed
+/*(See part 3 specification)
+// The digest is computed as:
+//
+aHash := hash ( nonceTPM | expiration | cpHashA | policyRef)
+// where:
+//
+hash()
+the hash associated with the signed auth
+//
+nonceTPM
+the nonceTPM value from the TPM2_StartAuthSession .
+//
+response If the authorization is not limited to this
+//
+session, the size of this value is zero.
+//
+expiration time limit on authorization set by authorizing object.
+//
+This 32-bit value is set to zero if the expiration
+//
+time is not being set.
+//
+cpHashA
+hash of the command parameters for the command being
+//
+approved using the hash algorithm of the PSAP session.
+//
+Set to NULLauth if the authorization is not limited
+//
+to a specific command.
+//
+policyRef
+hash of an opaque value determined by the authorizing
+//
+object. Set to the NULLdigest if no hash is present.
+*/
+// Start hash
+authHash.t.size = CryptStartHash(CryptGetSignHashAlg(&in->auth),
+&hashState);
+// add nonceTPM
+CryptUpdateDigest2B(&hashState, &in->nonceTPM.b);
+// add expiration
+CryptUpdateDigestInt(&hashState, sizeof(UINT32), (BYTE*) &in->expiration);
+// add cpHashA
+CryptUpdateDigest2B(&hashState, &in->cpHashA.b);
+// add policyRef
+CryptUpdateDigest2B(&hashState, &in->policyRef.b);
+// Complete digest
+CryptCompleteHash2B(&hashState, &authHash.b);
+// Validate Signature. A TPM_RC_SCHEME, TPM_RC_TYPE or TPM_RC_SIGNATURE
+// error may be returned at this point
+result = CryptVerifySignature(in->authObject, &authHash, &in->auth);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_PolicySigned_auth);
+}
+// Internal Data Update
+// Need the Name of the signing entity
+entityName.t.size = EntityGetName(in->authObject, &entityName.t.name);
+// Update policy with input policyRef and name of auth key
+// These values are updated even if the session is a trial session
+PolicyContextUpdate(TPM_CC_PolicySigned, &entityName, &in->policyRef,
+&in->cpHashA, authTimeout, session);
+// Command Output
+// Create ticket and timeout buffer if in->expiration < 0 and this is not
+// a trial session.
+// NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
+// when expiration is non-zero.
+if(
+in->expiration < 0
+&& session->attributes.isTrialPolicy == CLEAR
+)
+
+Page 238
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+
+Part 3: Commands
+
+{
+// Generate timeout buffer. The format of output timeout buffer is
+// TPM-specific.
+// Note: can't do a direct copy because the output buffer is a byte
+// array and it may not be aligned to accept a 64-bit value. The method
+// used has the side-effect of making the returned value a big-endian,
+// 64-bit value that is byte aligned.
+out->timeout.t.size = sizeof(UINT64);
+UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
+// Compute policy ticket
+TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
+authTimeout, &in->cpHashA, &in->policyRef, &entityName,
+&out->policyTicket);
+}
+else
+{
+// Generate a null ticket.
+// timeout buffer is null
+out->timeout.t.size = 0;
+// auth ticket is null
+out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
+out->policyTicket.hierarchy = TPM_RH_NULL;
+out->policyTicket.digest.t.size = 0;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 239
+October 31, 2013
+
+ Part 3: Commands
+
+25.4
+
+Trusted Platform Module Library
+
+TPM2_PolicySecret
+
+25.4.1 General Description
+This command includes a secret-based authorization to a policy. The caller proves knowledge of the
+secret value using an authorization session using the authValue associated with authHandle. A
+password session, an HMAC session, or a policy session containing TPM2_PolicyAuthValue() or
+TPM2_PolicyPassword() will satisfy this requirement.
+“If a policy session is used and use of the authValue of authHandle is not required, the TPM will return
+TPM_RC_MODE.”
+The secret is the authValue of authObject, which may be any TPM entity with a handle and an associated
+authValue. This includes the reserved handles (for example, Platform, Storage, and Endorsement), NV
+Indexes, and loaded objects.
+NOTE 1
+
+The authorization value for a hierarchy cannot be used in th is command if the hierarchy is disabled.
+
+If the authorization check fails, then the normal dictionary attack logic is invoked.
+If the authorization provided by the authorization session is valid, the command parameters are checked
+as described in 25.2.2.
+When all validations have succeeded, policySession→policyDigest is updated by PolicyUpdate() (see
+25.2.3).
+
+PolicyUpdate(TPM_CC_PolicySecret, authObject→Name, policyRef)
+
+(15)
+
+If the cpHashA command parameter is not an Empty Buffer, it is copied to cpHash in the session context.
+The TPM will optionally produce a ticket as described in 25.2.5.
+If the session is a trial session, policySession→policyDigest is updated as if the authorization is valid but
+no check is performed.
+NOTE 2
+
+If an HMAC is used to convey the authorization, a separate session is needed for the authorization.
+Because the HMAC in that authorization will include a nonce that prevents replay of the
+authorization, the value of the nonceTPM parameter in this command is limited. It is retained mostly
+to provide processing consistency with TPM2_PolicySigned().
+
+Page 240
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.4.2 Command and Response
+Table 115 — TPM2_PolicySecret Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+see clause 8
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicySecret
+
+TPMI_DH_ENTITY
+
+@authHandle
+
+handle for an entity providing the authorization
+Auth Index: 1
+Auth Role: USER
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_NONCE
+
+nonceTPM
+
+the policy nonce for the session
+If the nonce is not included in the authorization
+qualification, this field is the Empty Buffer.
+
+TPM2B_DIGEST
+
+cpHashA
+
+digest of the command parameters to which this
+authorization is limited
+This not the cpHash for this command but the cpHash
+for the command to which this policy session will be
+applied. If it is not limited, the parameter will be the
+Empty Buffer.
+
+TPM2B_NONCE
+
+policyRef
+
+a reference to a policy relating to the authorization –
+may be the Empty Buffer
+Size is limited to be no larger than the nonce size
+supported on the TPM.
+
+INT32
+
+expiration
+
+time when authorization will expire, measured in
+seconds from the time that nonceTPM was generated
+If expiration is zero, a NULL Ticket is returned.
+
+Table 116 — TPM2_PolicySecret Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_TIMEOUT
+
+timeout
+
+implementation-specific time value used to indicate to
+the TPM when the ticket expires; this ticket will use the
+TPMT_ST_AUTH_SECRET structure tag
+
+TPMT_TK_AUTH
+
+policyTicket
+
+produced if the command succeeds and expiration in
+the command was non-zero
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 241
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.4.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "PolicySecret_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+cpHash for policy was previously set to a value that is not the same
+as cpHashA
+
+TPM_RC_EXPIRED
+
+expiration indicates a time in the past
+
+TPM_RC_NONCE
+
+nonceTPM does not match the nonce associated with policySession
+
+TPM_RC_SIZE
+
+cpHashA is not the size of a digest for the hash associated with
+policySession
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+input policyID or expiration does not match the internal data in policy
+session
+
+TPM_RC
+TPM2_PolicySecret(
+PolicySecret_In
+PolicySecret_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+TPM_RC
+SESSION
+TPM2B_NAME
+UINT32
+
+result;
+*session;
+entityName;
+expiration = (in->expiration < 0)
+? -(in->expiration) : in->expiration;
+authTimeout = 0;
+
+)
+{
+
+UINT64
+// Input Validation
+
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+//Only do input validation if this is not a trial policy session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+if(expiration != 0)
+authTimeout = expiration * 1000 + session->startTime;
+result = PolicyParameterChecks(session, authTimeout,
+&in->cpHashA, &in->nonceTPM,
+RC_PolicySecret_nonceTPM,
+RC_PolicySecret_cpHashA,
+RC_PolicySecret_expiration);
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Internal Data Update
+// Need the name of the authorizing entity
+entityName.t.size = EntityGetName(in->authHandle, &entityName.t.name);
+// Update policy context with input policyRef and name of auth key
+// This value is computed even for trial sessions. Possibly update the cpHash
+PolicyContextUpdate(TPM_CC_PolicySecret, &entityName, &in->policyRef,
+
+Page 242
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+
+Part 3: Commands
+
+&in->cpHashA, authTimeout, session);
+// Command Output
+// Create ticket and timeout buffer if in->expiration < 0 and this is not
+// a trial session.
+// NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
+// when expiration is non-zero.
+if(
+in->expiration < 0
+&& session->attributes.isTrialPolicy == CLEAR
+)
+{
+// Generate timeout buffer. The format of output timeout buffer is
+// TPM-specific.
+// Note: can't do a direct copy because the output buffer is a byte
+// array and it may not be aligned to accept a 64-bit value. The method
+// used has the side-effect of making the returned value a big-endian,
+// 64-bit value that is byte aligned.
+out->timeout.t.size = sizeof(UINT64);
+UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
+// Compute policy ticket
+TicketComputeAuth(TPM_ST_AUTH_SECRET, EntityGetHierarchy(in->authHandle),
+authTimeout, &in->cpHashA, &in->policyRef,
+&entityName, &out->policyTicket);
+}
+else
+{
+// timeout buffer is null
+out->timeout.t.size = 0;
+// auth ticket is null
+out->policyTicket.tag = TPM_ST_AUTH_SECRET;
+out->policyTicket.hierarchy = TPM_RH_NULL;
+out->policyTicket.digest.t.size = 0;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 243
+October 31, 2013
+
+ Part 3: Commands
+
+25.5
+
+Trusted Platform Module Library
+
+TPM2_PolicyTicket
+
+25.5.1 General Description
+This command is similar to TPM2_PolicySigned() except that it takes a ticket instead of a signed
+authorization. The ticket represents a validated authorization that had an expiration time associated with
+it.
+The parameters of this command are checked as described in 25.2.2.
+If the checks succeed, the TPM uses the timeout, cpHashA, policyRef, and keyName to construct a ticket
+to compare with the value in ticket. If these tickets match, then the TPM will create a TPM2B_NAME
+(objectName) using authName and update the context of policySession by PolicyUpdate() (see 25.2.3).
+
+PolicyUpdate(commandCode, authName, policyRef)
+
+(16)
+
+If the structure tag of ticket is TPM_ST_AUTH_SECRET, then commandCode will be
+TPM_CC_PolicySecret. If the structure tag of ticket is TPM_ST_AUTH_SIGNED, then commandCode will
+be TPM_CC_PolicySIgned.
+If the cpHashA command parameter is not an Empty Buffer, it may be copied to cpHash in the session
+context.as described in 25.2.1.
+
+Page 244
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.5.2 Command and Response
+Table 117 — TPM2_PolicyTicket Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+see clause 8
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyTicket
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_TIMEOUT
+
+timeout
+
+time when authorization will expire
+The contents are TPM specific. This shall be the value
+returned when ticket was produced.
+
+TPM2B_DIGEST
+
+cpHashA
+
+digest of the command parameters to which this
+authorization is limited
+If it is not limited, the parameter will be the Empty
+Buffer.
+
+TPM2B_NONCE
+
+policyRef
+
+reference to a qualifier for the policy – may be the
+Empty Buffer
+
+TPM2B_NAME
+
+authName
+
+name of the object that provided the authorization
+
+TPMT_TK_AUTH
+
+ticket
+
+an authorization ticket returned by the TPM in response
+to a TPM2_PolicySigned() or TPM2_PolicySecret()
+
+Table 118 — TPM2_PolicyTicket Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 245
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.5.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "PolicyTicket_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+policy's cpHash was previously set to a different value
+
+TPM_RC_EXPIRED
+
+timeout value in the ticket is in the past and the ticket has expired
+
+TPM_RC_SIZE
+
+timeout or cpHash has invalid size for the
+
+TPM_RC_TICKET
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+ticket is not valid
+
+TPM_RC
+TPM2_PolicyTicket(
+PolicyTicket_In
+
+*in
+
+// IN: input parameter list
+
+TPM_RC
+SESSION
+UINT64
+TPMT_TK_AUTH
+TPM_CC
+
+result;
+*session;
+timeout;
+ticketToCompare;
+commandCode = TPM_CC_PolicySecret;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// NOTE: A trial policy session is not allowed to use this command.
+// A ticket is used in place of a previously given authorization. Since
+// a trial policy doesn't actually authenticate, the validated
+// ticket is not necessary and, in place of using a ticket, one
+// should use the intended authorization for which the ticket
+// would be a subsitute.
+if(session->attributes.isTrialPolicy)
+return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession;
+// Restore timeout data. The format of timeout buffer is TPM-specific.
+// In this implementation, we simply copy the value of timeout to the
+// buffer.
+if(in->timeout.t.size != sizeof(UINT64))
+return TPM_RC_SIZE + RC_PolicyTicket_timeout;
+timeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer);
+// Do the normal checks on the cpHashA and timeout values
+result = PolicyParameterChecks(session, timeout,
+&in->cpHashA, NULL,
+0,
+// no bad nonce return
+RC_PolicyTicket_cpHashA,
+RC_PolicyTicket_timeout);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Validate Ticket
+// Re-generate policy ticket by input parameters
+TicketComputeAuth(in->ticket.tag, in->ticket.hierarchy, timeout, &in->cpHashA,
+&in->policyRef, &in->authName, &ticketToCompare);
+
+Page 246
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
+Part 3: Commands
+
+// Compare generated digest with input ticket digest
+if(!Memory2BEqual(&in->ticket.digest.b, &ticketToCompare.digest.b))
+return TPM_RC_TICKET + RC_PolicyTicket_ticket;
+// Internal Data Update
+// Is this ticket to take the place of a TPM2_PolicySigned() or
+// a TPM2_PolicySecret()?
+if(in->ticket.tag == TPM_ST_AUTH_SIGNED)
+commandCode = TPM_CC_PolicySigned;
+else if(in->ticket.tag == TPM_ST_AUTH_SECRET)
+commandCode = TPM_CC_PolicySecret;
+else
+// There could only be two possible tag values. Any other value should
+// be caught by the ticket validation process.
+pAssert(FALSE);
+// Update policy context
+PolicyContextUpdate(commandCode, &in->authName, &in->policyRef,
+&in->cpHashA, timeout, session);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 247
+October 31, 2013
+
+ Part 3: Commands
+
+25.6
+
+Trusted Platform Module Library
+
+TPM2_PolicyOR
+
+25.6.1 General Description
+This command allows options in authorizations without requiring that the TPM evaluate all of the options.
+If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
+satisfies the policy. This command will indicate that one of the required sets of conditions has been
+satisfied.
+PolicySession→policyDigest is compared against the list of provided values. If the current
+policySession→policyDigest does not match any value in the list, the TPM shall return TPM_RC_VALUE.
+Otherwise, it will replace policySession→policyDigest with the digest of the concatenation of all of the
+digests and return TPM_RC_SUCCESS.
+If policySession is a trial session, the TPM will assume that policySession→policyDigest matches one of
+the list entries and compute the new value of policyDigest.
+The algorithm for computing the new value for policyDigest of policySession is:
+a) Concatenate all the digest values in pHashList:
+
+digests ≔ pHashList.digests[1].buffer || … || pHashList.digests[n].buffer
+NOTE 1
+
+(17)
+
+The TPM makes no check to see if the size of an entry matches the size of the digest of the
+policy.
+
+b) Reset policyDigest to a Zero Digest.
+c) Extend the command code and the hashes computed in step a) above:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyOR || digests)
+NOTE 2
+
+(18)
+
+The computation in b) and c) above is equivalent to:
+
+policyDigestnew ≔ HpolicyAlg(0…0 || TPM_CC_PolicyOR || digests)
+
+A TPM shall support a list with at least eight tagged digest values.
+NOTE 3
+
+If policies are to be portable between TPMs, then they should not use more than eight values.
+
+Page 248
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.6.2 Command and Response
+Table 119 — TPM2_PolicyOR Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyOR.
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPML_DIGEST
+
+pHashList
+
+the list of hashes to check for a match
+
+Table 120 — TPM2_PolicyOR Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 249
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.6.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "PolicyOR_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+no digest in pHashList matched the current value of policyDigest for
+policySession
+
+TPM_RC
+TPM2_PolicyOR(
+PolicyOR_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+UINT32
+
+*session;
+i;
+
+// Input Validation and Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Compare and Update Internal Session policy if match
+for(i = 0; i < in->pHashList.count; i++)
+{
+if(
+session->attributes.isTrialPolicy == SET
+|| (Memory2BEqual(&session->u2.policyDigest.b,
+&in->pHashList.digests[i].b))
+)
+{
+// Found a match
+HASH_STATE
+hashState;
+TPM_CC
+commandCode = TPM_CC_PolicyOR;
+// Start hash
+session->u2.policyDigest.t.size = CryptStartHash(session->authHashAlg,
+&hashState);
+// Set policyDigest to 0 string and add it to hash
+MemorySet(session->u2.policyDigest.t.buffer, 0,
+session->u2.policyDigest.t.size);
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add command code
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// Add each of the hashes in the list
+for(i = 0; i < in->pHashList.count; i++)
+{
+// Extend policyDigest
+CryptUpdateDigest2B(&hashState, &in->pHashList.digests[i].b);
+}
+// Complete digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+}
+// None of the values in the list matched the current policyDigest
+return TPM_RC_VALUE + RC_PolicyOR_pHashList;
+
+Page 250
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+
+Part 3: Commands
+
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 251
+October 31, 2013
+
+ Part 3: Commands
+
+25.7
+
+Trusted Platform Module Library
+
+TPM2_PolicyPCR
+
+25.7.1 General Description
+This command is used to cause conditional gating of a policy based on PCR. This allows one group of
+authorizations to occur when PCR are in one state and a different set of authorizations when the PCR are
+in a different state. 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 digest of the TPM PCR.
+The TPM will modify the pcrs parameter so that bits that correspond to unimplemented PCR are CLEAR.
+If policySession is not a trial policy session, the TPM will use the modified value of pcrs to select PCR
+values to hash according to Part 1, Selecting Multiple PCR. The hash algorithm of the policy session is
+used to compute a digest (digestTPM) of the selected PCR. If pcrDigest does not have a length of zero,
+then it is compared to digestTPM; and if the values do not match, the TPM shall return TPM_RC_VALUE
+and make no change to policySession→policyDigest. If the values match, or if the length of pcrDigest is
+zero, then policySession→policyDigest is extended by:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPCR || pcrs || digestTPM)
+
+(19)
+
+where
+
+pcrs
+
+the pcrs parameter with bits corresponding to unimplemented
+PCR set to 0
+
+digestTPM
+
+the digest of the selected PCR using the hash algorithm of the
+policy session
+
+NOTE 1
+
+If the caller provides the expected PCR value, the intention is that the policy evaluation stop at that
+point if the PCR do not match. If the caller does not provide the expected PCR value, then the
+validity of the settings will not be determined until an attempt is made to use the policy for
+authorization. If the policy is constructed such that the PCR check comes before user authorization
+checks, this early termination would allow software to avoid unnecessary prompts for user input to
+satisfy a policy that would fail later due to incorr ect PCR values.
+
+After this command completes successfully, the TPM shall return TPM_RC_PCR_CHANGED if the policy
+session is used for authorization and the PCR are not known to be correct.
+The TPM uses a “generation” number (pcrUpdateCounter) that is incremented each time PCR are
+updated (unless the PCR being changed is specified not to cause a change to this counter). The value of
+this counter is stored in the policy session context (policySession→pcrUpdateCounter) when this
+command is executed. When the policy is used for authorization, the current value of the counter is
+compared to the value in the policy session context and the authorization will fail if the values are not the
+same.
+When this command is executed, policySession→pcrUpdateCounter is checked to see if it has been
+previously set (in the reference implementation, it has a value of zero if not previously set). If it has been
+set, it will be compared with the current value of pcrUpdateCounter to determine if any PCR changes
+have occurred. If the values are different, the TPM shall return TPM_RC_PCR_CHANGED. If
+policySession→pcrUpdateCounter has not been set, then it is set to the current value of
+pcrUpdateCounter.
+If policySession is a trial policy session, the TPM will not check any PCR and will compute:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPCR || pcrs || pcrDigest)
+
+(20)
+
+In this computation, pcrs is the input parameter without modification.
+NOTE 2
+
+The pcrs parameter is expected to match the configuration of the TPM for which the policy is being
+computed which may not be the same as the TPM on which the trial policy is being computed.
+
+Page 252
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.7.2 Command and Response
+Table 121 — TPM2_PolicyPCR Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyPCR
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+pcrDigest
+
+expected digest value of the selected PCR using the
+hash algorithm of the session; may be zero length
+
+TPML_PCR_SELECTION
+
+pcrs
+
+the PCR to include in the check digest
+
+Table 122 — TPM2_PolicyPCR Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 253
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PolicyPCR_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+if provided, pcrDigest does not match the current PCR settings
+
+TPM_RC_PCR_CHANGED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+a previous TPM2_PolicyPCR() set pcrCounter and it has changed
+
+TPM_RC
+TPM2_PolicyPCR(
+PolicyPCR_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM2B_DIGEST
+BYTE
+UINT32
+BYTE
+TPM_CC
+HASH_STATE
+
+*session;
+pcrDigest;
+pcrs[sizeof(TPML_PCR_SELECTION)];
+pcrSize;
+*buffer;
+commandCode = TPM_CC_PolicyPCR;
+hashState;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Do validation for non trial session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// Make sure that this is not going to invalidate a previous PCR check
+if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter)
+return TPM_RC_PCR_CHANGED;
+// Compute current PCR digest
+PCRComputeCurrentDigest(session->authHashAlg, &in->pcrs, &pcrDigest);
+// If the caller specified the PCR digest and it does not
+// match the current PCR settings, return an error..
+if(in->pcrDigest.t.size != 0)
+{
+if(!Memory2BEqual(&in->pcrDigest.b, &pcrDigest.b))
+return TPM_RC_VALUE + RC_PolicyPCR_pcrDigest;
+}
+}
+else
+{
+// For trial session, just use the input PCR digest
+pcrDigest = in->pcrDigest;
+}
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(
+policyDigestold || TPM_CC_PolicyPCR
+//
+|| pcrs || pcrDigest)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+
+Page 254
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+Part 3: Commands
+
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add PCRS
+buffer = pcrs;
+pcrSize = TPML_PCR_SELECTION_Marshal(&in->pcrs, &buffer, NULL);
+CryptUpdateDigest(&hashState, pcrSize, pcrs);
+// add PCR digest
+CryptUpdateDigest2B(&hashState, &pcrDigest.b);
+// complete the hash and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update pcrCounter in session context for non trial session
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+session->pcrCounter = gr.pcrCounter;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 255
+October 31, 2013
+
+ Part 3: Commands
+
+25.8
+
+Trusted Platform Module Library
+
+TPM2_PolicyLocality
+
+25.8.1 General Description
+This command indicates that the authorization will be limited to a specific locality.
+policySession→commandLocality is a parameter kept in the session context. It is initialized when the
+policy session is started to allow the policy to apply to any locality.
+If locality has a value greater than 31, then an extended locality is indicated. For an extended locality, the
+TPM will validate that policySession→commandLocality is has not previously been set or that the current
+value of policySession→commandLocality is the same as locality (TPM_RC_RANGE).
+When locality is not an extended locality, the TPM will validate that the policySession→commandLocality
+is not set or is not set to an extended locality value (TPM_RC_RANGE). If not the TPM will disable any
+locality not SET in the locality parameter. If the result of disabling localities results in no locality being
+enabled, the TPM will return TPM_RC_RANGE.
+If no error occurred in the validation of locality, policySession→policyDigest is extended with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyLocality || locality)
+
+(21)
+
+Then policySession→commandLocality is updated to indicate which localities are still allowed after
+execution of TPM2_PolicyLocality().
+When the policy session is used to authorize a command, the authorization will fail if the locality used for
+the command is not one of the enabled localities in policySession→commandLocality.
+
+Page 256
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.8.2 Command and Response
+Table 123 — TPM2_PolicyLocality Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyLocality
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPMA_LOCALITY
+
+locality
+
+the allowed localities for the policy
+
+Table 124 — TPM2_PolicyLocality Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 257
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.8.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "PolicyLocality_fp.h"
+
+Limit a policy to a specific locality
+Error Returns
+TPM_RC_RANGE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+all the locality values selected by locality have been disabled by
+previous TPM2_PolicyLocality() calls.
+
+TPM_RC
+TPM2_PolicyLocality(
+PolicyLocality_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+BYTE
+BYTE
+UINT32
+BYTE
+TPM_CC
+HASH_STATE
+
+*session;
+marshalBuffer[sizeof(TPMA_LOCALITY)];
+prevSetting[sizeof(TPMA_LOCALITY)];
+marshalSize;
+*buffer;
+commandCode = TPM_CC_PolicyLocality;
+hashState;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Get new locality setting in canonical form
+buffer = marshalBuffer;
+marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, NULL);
+// Its an error if the locality parameter is zero
+if(marshalBuffer[0] == 0)
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// Get existing locality setting in canonical form
+buffer = prevSetting;
+TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
+// If the locality has been previously set, then it needs to be the same
+// tye as the input locality (i.e. both extended or both normal
+if(prevSetting[0] != 0 && ((prevSetting[0] <= 0) != (marshalBuffer[0] <= 0)))
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// See if the input is a regular or extended locality
+if(marshalBuffer[0] < 32)
+{
+// For regular locality
+// The previous setting must not be an extended locality
+if(prevSetting[0] > 31)
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// if there was no previous setting, start with all normal localities
+// enabled
+if(prevSetting[0] == 0)
+prevSetting[0] = 0x1F;
+// AND the new setting with the previous setting and store it in prevSetting
+
+Page 258
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+
+Part 3: Commands
+
+prevSetting[0] &= marshalBuffer[0];
+// The result setting can not be 0
+if(prevSetting[0] == 0)
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+}
+else
+{
+// for extended locality
+// if the locality has already been set, then it must match the
+if(prevSetting[0] != 0 && prevSetting[0] != marshalBuffer[0])
+return TPM_RC_RANGE + RC_PolicyLocality_locality;
+// Setting is OK
+prevSetting[0] = marshalBuffer[0];
+}
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyLocality || locality)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add input locality
+CryptUpdateDigest(&hashState, marshalSize, marshalBuffer);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update session locality by unmarshal function. The function must succeed
+// because both input and existing locality setting have been validated.
+buffer = prevSetting;
+TPMA_LOCALITY_Unmarshal(&session->commandLocality, &buffer,
+(INT32 *) &marshalSize);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 259
+October 31, 2013
+
+ Part 3: Commands
+
+25.9
+
+Trusted Platform Module Library
+
+TPM2_PolicyNV
+
+25.9.1 General Description
+This command is used to cause conditional gating of a policy based on the contents of an NV Index.
+If policySession is a trial policy session, the TPM will update policySession→policyDigest as shown in
+equations (22) and (23) below and return TPM_RC_SUCCESS. It will not perform any validation. The
+remainder of this general description would apply only if policySession is not a trial policy session.
+An authorization session providing authorization to read the NV Index shall be provided.
+NOTE 1
+
+If read access is controlled by policy, the policy should include a branch that authorizes a
+TPM2_PolicyNV().
+
+If TPMA_NV_WRITTEN is not SET in the NV Index, the TPM shall return TPM_RC_NV_UNINITIALIZED.
+The TPM will validate that the size of operandB plus offset is not greater than the size of the NV Index. If
+it is, the TPM shall return TPM_RC_SIZE.
+The TPM will perform the indicated arithmetic check on the indicated portion of the selected NV Index. If
+the check fails, the TPM shall return TPM_RC_POLICY and not change policySession→policyDigest. If
+the check succeeds, the TPM will hash the arguments:
+
+args ≔ HpolicyAlg(operand.buffer || offset || operation)
+
+(22)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+operandB
+
+the value used for the comparison
+
+offset
+
+offset from the start of the NV Index data to start the comparison
+
+operation
+
+the operation parameter indicating the comparison being
+performed
+
+The value of args and the Name of the NV Index are extended to policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNV || args || nvIndex→Name)
+
+(23)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+args
+
+value computed in equation (22)
+
+nvIndex→Name
+
+the Name of the NV Index
+
+The signed arithmetic operations are performed using twos-compliment.
+Magnitude comparisons assume that the octet at offset zero in the referenced NV location and in
+operandB contain the most significant octet of the data.
+NOTE 2
+
+When an Index is written, it has a different authorization name than an Index that has not been
+written. It is possible to use this change in the NV Index to create a write-once Index.
+
+Page 260
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.9.2 Command and Response
+Table 125 — TPM2_PolicyNV Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyNV
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index of the area to read
+Auth Index: None
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_OPERAND
+
+operandB
+
+the second operand
+
+UINT16
+
+offset
+
+the offset in the NV Index for the start of operand A
+
+TPM_EO
+
+operation
+
+the comparison to make
+
+Table 126 — TPM2_PolicyNV Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 261
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.9.3 Detailed Actions
+1
+2
+3
+4
+
+#include
+#include
+#include
+#include
+
+"InternalRoutines.h"
+"PolicyNV_fp.h"
+"Policy_spt_fp.h"
+"NV_spt_fp.h"
+
+// Include NV support routine for read access check
+
+Error Returns
+TPM_RC_AUTH_TYPE
+
+NV index authorization type is not correct
+
+TPM_RC_NV_LOCKED
+
+NV index read locked
+
+TPM_RC_NV_UNINITIALIZED
+
+the NV index has not been initialized
+
+TPM_RC_POLICY
+
+the comparison to the NV contents failed
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+
+Meaning
+
+the size of nvIndex data starting at offset is less than the size of
+operandB
+
+TPM_RC
+TPM2_PolicyNV(
+PolicyNV_In
+
+*in
+
+// IN: input parameter list
+
+TPM_RC
+SESSION
+NV_INDEX
+BYTE
+TPM2B_NAME
+TPM_CC
+HASH_STATE
+TPM2B_DIGEST
+
+result;
+*session;
+nvIndex;
+nvBuffer[sizeof(in->operandB.t.buffer)];
+nvName;
+commandCode = TPM_CC_PolicyNV;
+hashState;
+argHash;
+
+)
+{
+
+// Input Validation
+// Get NV index information
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+//If this is a trial policy, skip all validations and the operation
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// NV Read access check. NV index should be allowed for read. A
+// TPM_RC_AUTH_TYPE or TPM_RC_NV_LOCKED error may be return at this
+// point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS) return result;
+// Valid NV data size should not be smaller than input operandB size
+if((nvIndex.publicArea.dataSize - in->offset) < in->operandB.t.size)
+return TPM_RC_SIZE + RC_PolicyNV_operandB;
+// Arithmetic Comparison
+// Get NV data. The size of NV data equals the input operand B size
+NvGetIndexData(in->nvIndex, &nvIndex, in->offset,
+in->operandB.t.size, nvBuffer);
+switch(in->operation)
+
+Page 262
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+
+Part 3: Commands
+
+{
+case TPM_EO_EQ:
+// compare A = B
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_NEQ:
+// compare A != B
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GT:
+// compare A > B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GT:
+// compare A > B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LT:
+// compare A < B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LT:
+// compare A < B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GE:
+// compare A >= B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GE:
+// compare A >= B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LE:
+// compare A <= B signed
+if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LE:
+// compare A <= B unsigned
+if(CryptCompare(in->operandB.t.size, nvBuffer,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_BITSET:
+// All bits SET in B are SET in A. ((A&B)=B)
+{
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+!= 0)
+
+== 0)
+
+<= 0)
+
+<= 0)
+
+>= 0)
+
+>= 0)
+
+< 0)
+
+< 0)
+
+> 0)
+
+> 0)
+
+Page 263
+October 31, 2013
+
+ Part 3: Commands
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+
+Trusted Platform Module Library
+
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if((nvBuffer[i] & in->operandB.t.buffer[i])
+!= in->operandB.t.buffer[i])
+return TPM_RC_POLICY;
+}
+break;
+case TPM_EO_BITCLEAR:
+// All bits SET in B are CLEAR in A. ((A&B)=0)
+{
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if((nvBuffer[i] & in->operandB.t.buffer[i]) != 0)
+return TPM_RC_POLICY;
+}
+break;
+default:
+pAssert(FALSE);
+break;
+}
+}
+// Internal Data Update
+// Start argument hash
+argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
+// add operandB
+CryptUpdateDigest2B(&hashState, &in->operandB.b);
+// add offset
+CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
+// add operation
+CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
+// complete argument digest
+CryptCompleteHash2B(&hashState, &argHash.b);
+// Update policyDigest
+// Start digest
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add argument digest
+CryptUpdateDigest2B(&hashState, &argHash.b);
+// Adding nvName
+nvName.t.size = EntityGetName(in->nvIndex, &nvName.t.name);
+CryptUpdateDigest2B(&hashState, &nvName.b);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+
+Page 264
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.10 TPM2_PolicyCounterTimer
+25.10.1
+
+General Description
+
+This command is used to cause conditional gating of a policy based on the contents of the
+TPMS_TIME_INFO structure.
+If policySession is a trial policy session, the TPM will update policySession→policyDigest as shown in
+equations (24) and (25) below and return TPM_RC_SUCCESS. It will not perform any validation. The
+remainder of this general description would apply only if policySession is not a trial policy session.
+The TPM will perform the indicated arithmetic check on the indicated portion of the TPMS_TIME_INFO
+structure. If the check fails, the TPM shall return TPM_RC_POLICY and not change
+policySession→policyDigest. If the check succeeds, the TPM will hash the arguments:
+
+args ≔ HpolicyAlg(operandB.buffer || offset || operation)
+
+(24)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+operandB.buffer
+
+the value used for the comparison
+
+offset
+
+offset from the start of the TPMS_TIME_INFO structure at which
+the comparison starts
+
+operation
+
+the operation parameter indicating the comparison being
+performed
+
+The value of args is extended to policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCounterTimer || args)
+
+(25)
+
+where
+
+HpolicyAlg()
+
+hash function using the algorithm of the policy session
+
+args
+
+value computed in equation (24)
+
+The signed arithmetic operations are performed using twos-compliment.
+Magnitude comparisons assume that the octet at offset zero in the referenced location and in operandB
+contain the most significant octet of the data.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 265
+October 31, 2013
+
+ Part 3: Commands
+
+25.10.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 127 — TPM2_PolicyCounterTimer Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyCounterTimer
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_OPERAND
+
+operandB
+
+the second operand
+
+UINT16
+
+offset
+
+the offset in TPMS_TIME_INFO structure for the start of
+operand A
+
+TPM_EO
+
+operation
+
+the comparison to make
+
+Table 128 — TPM2_PolicyCounterTimer Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 266
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.10.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyCounterTimer_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_POLICY
+
+the comparison of the selected portion of the TPMS_TIME_INFO with
+operandB failed
+
+TPM_RC_RANGE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+
+offset + size exceed size of TPMS_TIME_INFO structure
+
+TPM_RC
+TPM2_PolicyCounterTimer(
+PolicyCounterTimer_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+SESSION
+TIME_INFO
+TPM_CC
+HASH_STATE
+TPM2B_DIGEST
+
+result;
+*session;
+infoData;
+// data buffer of TPMS_TIME_INFO
+commandCode = TPM_CC_PolicyCounterTimer;
+hashState;
+argHash;
+
+// Input Validation
+// If the command is going to use any part of the counter or timer, need
+// to verify that time is advancing.
+// The time and clock vales are the first two 64-bit values in the clock
+if(in->offset < <K>sizeof(UINT64) + sizeof(UINT64))
+{
+// Using Clock or Time so see if clock is running. Clock doesn't run while
+// NV is unavailable.
+// TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+//If this is a trial policy, skip all validations and the operation
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// Get time data info. The size of time info data equals the input
+// operand B size. A TPM_RC_RANGE error may be returned at this point
+result = TimeGetRange(in->offset, in->operandB.t.size, &infoData);
+if(result != TPM_RC_SUCCESS) return result;
+// Arithmetic Comparison
+switch(in->operation)
+{
+case TPM_EO_EQ:
+// compare A = B
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer) != 0)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_NEQ:
+// compare A != B
+if(CryptCompare(in->operandB.t.size, infoData,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 267
+October 31, 2013
+
+ Part 3: Commands
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+
+Trusted Platform Module Library
+
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GT:
+// compare A > B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GT:
+// compare A > B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LT:
+// compare A < B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LT:
+// compare A < B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_GE:
+// compare A >= B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_GE:
+// compare A >= B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_SIGNED_LE:
+// compare A <= B signed
+if(CryptCompareSigned(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_UNSIGNED_LE:
+// compare A <= B unsigned
+if(CryptCompare(in->operandB.t.size, infoData,
+in->operandB.t.size, in->operandB.t.buffer)
+return TPM_RC_POLICY;
+break;
+case TPM_EO_BITSET:
+// All bits SET in B are SET in A. ((A&B)=B)
+{
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if(
+(infoData[i] & in->operandB.t.buffer[i])
+!= in->operandB.t.buffer[i])
+return TPM_RC_POLICY;
+}
+break;
+case TPM_EO_BITCLEAR:
+// All bits SET in B are CLEAR in A. ((A&B)=0)
+{
+
+Page 268
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+== 0)
+
+<= 0)
+
+<= 0)
+
+>= 0)
+
+>= 0)
+
+< 0)
+
+< 0)
+
+> 0)
+
+> 0)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+
+Part 3: Commands
+
+UINT32 i;
+for (i = 0; i < in->operandB.t.size; i++)
+if((infoData[i] & in->operandB.t.buffer[i]) != 0)
+return TPM_RC_POLICY;
+}
+break;
+default:
+pAssert(FALSE);
+break;
+}
+}
+// Internal Data Update
+// Start argument list hash
+argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
+// add operandB
+CryptUpdateDigest2B(&hashState, &in->operandB.b);
+// add offset
+CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
+// add operation
+CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
+// complete argument hash
+CryptCompleteHash2B(&hashState, &argHash.b);
+// update policyDigest
+// start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add argument digest
+CryptUpdateDigest2B(&hashState, &argHash.b);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 269
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.11 TPM2_PolicyCommandCode
+25.11.1
+
+General Description
+
+This command indicates that the authorization will be limited to a specific command code.
+If policySession→commandCode has its default value, then it will be set to code. If
+policySession→commandCode does not have its default value, then the TPM will return
+TPM_RC_VALUE if the two values are not the same.
+If code is not implemented, the TPM will return TPM_RC_POLICY_CC.
+If the TPM does not return an error, it will update policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCommandCode || code)
+
+(26)
+
+NOTE 1
+
+If a previous TPM2_PolicyCommandCode() had been executed, then it is probable that the policy
+expression is improperly formed but the TPM does not return an error.
+
+NOTE 2
+
+A TPM2_PolicyOR() would be used to allow an authorization to be used for multiple commands.
+
+When the policy session is used to authorize a command, the TPM will fail the command if the
+commandCode of that command does not match policySession→commandCode.
+This command, or TPM2_PolicyDuplicationSelect(), is required to enable the policy to be used for ADMIN
+role authorization.
+EXAMPLE
+
+Before TPM2_Certify() can
+TPM_CC_Certify is required.
+
+Page 270
+October 31, 2013
+
+be
+
+executed,
+
+TPM2_PolicyCommandCode()
+
+Published
+Copyright © TCG 2006-2013
+
+with
+
+code
+
+set
+
+to
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.11.2
+
+Part 3: Commands
+
+Command and Response
+Table 129 — TPM2_PolicyCommandCode Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyCommandCode
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM_CC
+
+code
+
+the allowed commandCode
+
+Table 130 — TPM2_PolicyCommandCode Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 271
+October 31, 2013
+
+ Part 3: Commands
+
+25.11.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyCommandCode_fp.h"
+Error Returns
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+commandCode of policySession previously set to a different value
+
+TPM_RC
+TPM2_PolicyCommandCode(
+PolicyCommandCode_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyCommandCode;
+hashState;
+
+// Input validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+if(session->commandCode != 0 && session->commandCode != in->code)
+return TPM_RC_VALUE + RC_PolicyCommandCode_code;
+if(!CommandIsImplemented(in->code))
+return TPM_RC_POLICY_CC + RC_PolicyCommandCode_code;
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCommandCode || code)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add input commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &in->code);
+// complete the hash and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update commandCode value in session context
+session->commandCode = in->code;
+return TPM_RC_SUCCESS;
+}
+
+Page 272
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.12 TPM2_PolicyPhysicalPresence
+25.12.1
+
+General Description
+
+This command indicates that physical presence will need to be asserted at the time the authorization is
+performed.
+If this command is successful, policySession→isPPRequired will be SET to indicate that this check is
+required when the policy is used for authorization. Additionally, policySession→policyDigest is extended
+with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPhysicalPresence)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+(27)
+
+Page 273
+October 31, 2013
+
+ Part 3: Commands
+
+25.12.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 131 — TPM2_PolicyPhysicalPresence Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyPhysicalPresence
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+Table 132 — TPM2_PolicyPhysicalPresence Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 274
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.12.3
+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
+33
+34
+35
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyPhysicalPresence_fp.h"
+
+TPM_RC
+TPM2_PolicyPhysicalPresence(
+PolicyPhysicalPresence_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyPhysicalPresence;
+hashState;
+
+// Internal Data Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyPhysicalPresence)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update session attribute
+session->attributes.isPPRequired = SET;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 275
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.13 TPM2_PolicyCpHash
+25.13.1
+
+General Description
+
+This command is used to allow a policy to be bound to a specific command and command parameters.
+TPM2_PolicySigned(), TPM2_PolicySecret(), and TPM2_PolicyTIcket() are designed to allow an
+authorizing entity to execute an arbitrary command as the cpHashA parameter of those commands is not
+included in policySession→policyDigest. TPM2_PolicyCommandCode() allows the policy to be bound to a
+specific Command Code so that only certain entities may authorize specific command codes. This
+command allows the policy to be restricted such that an entity may only authorize a command with a
+specific set of parameters.
+If policySession→cpHash is already set and not the same as cpHashA, then the TPM shall return
+TPM_RC_VALUE. If cpHashA does not have the size of the policySession→policyDigest, the TPM shall
+return TPM_RC_SIZE.
+If the cpHashA checks succeed, policySession→cpHash
+policySession→policyDigest is updated with
+
+is
+
+set
+
+to
+
+cpHashA
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCpHash || cpHashA)
+
+Page 276
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+and
+(28)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.13.2
+
+Part 3: Commands
+
+Command and Response
+Table 133 — TPM2_PolicyCpHash Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyCpHash
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+cpHashA
+
+the cpHash added to the policy
+
+Table 134 — TPM2_PolicyCpHash Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 277
+October 31, 2013
+
+ Part 3: Commands
+
+25.13.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyCpHash_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+cpHash of policySession has previously been set to a different value
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+
+cpHashA is not the size of a digest produced by the hash algorithm
+associated with policySession
+
+TPM_RC
+TPM2_PolicyCpHash(
+PolicyCpHash_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyCpHash;
+hashState;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// A new cpHash is given in input parameter, but cpHash in session context
+// is not empty, or is not the same as the new cpHash
+if(
+in->cpHashA.t.size != 0
+&& session->u1.cpHash.t.size != 0
+&& !Memory2BEqual(&in->cpHashA.b, &session->u1.cpHash.b)
+)
+return TPM_RC_CPHASH;
+// A valid cpHash must have the same size as session hash digest
+if(in->cpHashA.t.size != CryptGetHashDigestSize(session->authHashAlg))
+return TPM_RC_SIZE + RC_PolicyCpHash_cpHashA;
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash || cpHashA)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add cpHashA
+CryptUpdateDigest2B(&hashState, &in->cpHashA.b);
+// complete the digest and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update cpHash in session context
+session->u1.cpHash = in->cpHashA;
+session->attributes.iscpHashDefined = SET;
+return TPM_RC_SUCCESS;
+
+Page 278
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+53
+
+Part 3: Commands
+
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 279
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.14 TPM2_PolicyNameHash
+25.14.1
+
+General Description
+
+This command allows a policy to be bound to a specific set of TPM entities without being bound to the
+parameters of the command. This is most useful for commands such as TPM2_Duplicate() and for
+TPM2_PCR_Event() when the referenced PCR requires a policy.
+The nameHash parameter should contain the digest of the Names associated with the handles to be used
+in the authorized command.
+EXAMPLE
+
+For the TPM2_Duplicate() command, two handles are provided. One is the handle of the object
+being duplicated and the other is the handle of the new parent. For that command, nameHash would
+contain:
+
+nameHash ≔ H policyAlg (objectHandle→Name || newParentHandle→Name)
+
+If policySession→cpHash is already set, the TPM shall return TPM_RC_VALUE. If the size of nameHash
+is not the size of policySession→policyDigest, the TPM shall return TPM_RC_SIZE. Otherwise,
+policySession→cpHash is set to nameHash.
+If this command completes successfully, the cpHash of the authorized command will not be used for
+validation. Only the digest of the Names associated with the handles in the command will be used.
+NOTE 1
+
+This allows the space normally
+policySession→nameHash instead.
+
+used
+
+to
+
+hold
+
+policySession→cpHash
+
+to
+
+be
+
+used
+
+for
+
+The policySession→policyDigest will be updated with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNameHash || nameHash)
+NOTE 2
+
+(29)
+
+This command will often be used with TPM2_PolicyAuthorize() where the owner of the object being
+duplicated provides approval for their object to be migrated to a specific new parent.
+
+Page 280
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.14.2
+
+Part 3: Commands
+
+Command and Response
+Table 135 — TPM2_PolicyNameHash Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyNameHash
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+nameHash
+
+the digest to be added to the policy
+
+Table 136 — TPM2_PolicyNameHash Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 281
+October 31, 2013
+
+ Part 3: Commands
+
+25.14.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyNameHash_fp.h"
+Error Returns
+TPM_RC_CPHASH
+
+nameHash has been previously set to a different value
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+
+nameHash is not the size of the digest produced by the hash
+algorithm associated with policySession
+
+TPM_RC
+TPM2_PolicyNameHash(
+PolicyNameHash_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyNameHash;
+hashState;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// A new nameHash is given in input parameter, but cpHash in session context
+// is not empty
+if(in->nameHash.t.size != 0 && session->u1.cpHash.t.size != 0)
+return TPM_RC_CPHASH;
+// A valid nameHash must have the same size as session hash digest
+if(in->nameHash.t.size != CryptGetHashDigestSize(session->authHashAlg))
+return TPM_RC_SIZE + RC_PolicyNameHash_nameHash;
+// Internal Data Update
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNameHash || nameHash)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add nameHash
+CryptUpdateDigest2B(&hashState, &in->nameHash.b);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// clear iscpHashDefined bit to indicate now this field contains a nameHash
+session->attributes.iscpHashDefined = CLEAR;
+// update nameHash in session context
+session->u1.cpHash = in->nameHash;
+return TPM_RC_SUCCESS;
+}
+
+Page 282
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.15 TPM2_PolicyDuplicationSelect
+25.15.1
+
+General Description
+
+This command allows qualification of duplication to allow duplication to a selected new parent.
+If this command not used in conjunction with TPM2_PolicyAuthorize(), then only the new parent is
+selected.
+EXAMPLE
+
+When an object is created when the list of allowed duplication targets is known, the policy would be
+created with includeObject CLEAR.
+
+NOTE 1
+
+Only the new parent may be selected because, without TPM2_PolicyAuthorize() , the Name of the
+Object to be duplicated would need to be known at the time that Object's policy is created. However,
+since the Name of the Object includes its policy, the Name is not known.
+
+If used in conjunction with TPM2_PolicyAuthorize(), then the authorizer of the new policy has the option
+of selecting just the new parent or of selecting both the new parent and the duplication Object..
+NOTE 2
+
+If the authorizing entity for an TPM2_PolicyAuthorize() only specifies the new parent, then that
+authorization may be applied to the duplication of any number of other Objects. If the authorizing
+entity specifies both a new parent and the duplicated Object, then the authorization only applies to
+that pairing of Object and new parent.
+
+If either policySession→cpHash or policySession→nameHash has been previously set, the TPM shall
+return TPM_RC_CPHASH. Otherwise, policySession→nameHash will be set to:
+
+nameHash ≔ HpolicyAlg(objectName || newParentName)
+
+(30)
+
+It is allowed that policySesion→nameHash and policySession→cpHash share the same memory
+space.
+
+NOTE 3
+
+The policySession→policyDigest will be updated according to the setting of includeObject. If equal to
+YES, policySession→policyDigest is updated by:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyDuplicationSelect ||
+objectName || newParentName || includeObject)
+
+(31)
+
+If includeObject is NO, policySession→policyDigest is updated by:
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyDuplicationSelect ||
+newParentName || includeObject)
+NOTE 4
+
+(32)
+
+PolicySession→CpHash receives the digest of both Names so that the check performed in
+TPM2_Duplicate() may be the same regardless of which Names are included in
+policySession→policyDigest. This means that, when TPM2_PolicyDuplicationSelect() is executed, it
+is only valid for a specific pair of duplication object and new parent.
+
+If the command succeeds, commandCode in the policy session context is set to TPM_CC_Duplicate.
+NOTE 5
+
+The normal use of this command is before a TPM2_PolicyAuthorize(). An authorized entity would
+approve a policyDigest that allowed duplication to a specific new parent. The authorizing entity may
+want to limit the authorization so that the approval allows only a specific object to be duplicated to
+the new parent. In that case, the authorizing entity would approve the policyDigest of equation (31).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 283
+October 31, 2013
+
+ Part 3: Commands
+
+25.15.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 137 — TPM2_PolicyDuplicationSelect Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyDuplicationSelect
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_NAME
+
+objectName
+
+the Name of the object to be duplicated
+
+TPM2B_NAME
+
+newParentName
+
+the Name of the new parent
+
+TPMI_YES_NO
+
+includeObject
+
+if YES, the objectName will be included in the value in
+policySession→policyDigest
+
+Table 138 — TPM2_PolicyDuplicationSelect Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 284
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.15.3
+1
+2
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyDuplicationSelect_fp.h"
+Error Returns
+TPM_RC_COMMAND_CODE
+
+commandCode of 'policySession; is not empty
+
+TPM_RC_CPHASH
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+cpHash of policySession is not empty
+
+TPM_RC
+TPM2_PolicyDuplicationSelect(
+PolicyDuplicationSelect_In *in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+HASH_STATE
+TPM_CC
+
+*session;
+hashState;
+commandCode = TPM_CC_PolicyDuplicationSelect;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// cpHash in session context must be empty
+if(session->u1.cpHash.t.size != 0)
+return TPM_RC_CPHASH;
+// commandCode in session context must be empty
+if(session->commandCode != 0)
+return TPM_RC_COMMAND_CODE;
+// Internal Data Update
+// Update name hash
+session->u1.cpHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
+// add objectName
+CryptUpdateDigest2B(&hashState, &in->objectName.b);
+// add new parent name
+CryptUpdateDigest2B(&hashState, &in->newParentName.b);
+// complete hash
+CryptCompleteHash2B(&hashState, &session->u1.cpHash.b);
+// update policy hash
+// Old policyDigest size should be the same as the new policyDigest size since
+// they are using the same hash algorithm
+session->u2.policyDigest.t.size
+= CryptStartHash(session->authHashAlg, &hashState);
+// add old policy
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add command code
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add objectName
+if(in->includeObject == YES)
+CryptUpdateDigest2B(&hashState, &in->objectName.b);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 285
+October 31, 2013
+
+ Part 3: Commands
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+
+Trusted Platform Module Library
+
+// add new parent name
+CryptUpdateDigest2B(&hashState, &in->newParentName.b);
+// add includeObject
+CryptUpdateDigestInt(&hashState, sizeof(TPMI_YES_NO), &in->includeObject);
+// complete digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// clear iscpHashDefined bit to indicate now this field contains a nameHash
+session->attributes.iscpHashDefined = CLEAR;
+// set commandCode in session context
+session->commandCode = TPM_CC_Duplicate;
+return TPM_RC_SUCCESS;
+}
+
+Page 286
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.16 TPM2_PolicyAuthorize
+25.16.1
+
+General Description
+
+This command allows policies to change. If a policy were static, then it would be difficult to add users to a
+policy. This command lets a policy authority sign a new policy so that it may be used in an existing policy.
+The authorizing entity signs a structure that contains
+
+aHash ≔ HaHashAlg(approvedPolicy || policyRef)
+
+(33)
+
+The aHashAlg is required to be the nameAlg of the key used to sign the aHash. The aHash value is then
+signed (symmetric or asymmetric) by keySign. That signature is then checked by the TPM in
+TPM2_VerifySignature() which produces a ticket by
+
+HMAC(proof, (TPM_ST_VERIFIED || aHash || keySign→Name))
+NOTE
+
+(34)
+
+The reason for the validation is because of the expectation that the policy will be used multiple times
+and it is more efficient to check a ticket than to load an object each time to chec k a signature.
+
+The ticket is then used in TPM2_PolicyAuthorize() to validate the parameters.
+The keySign parameter is required to be a valid object name using nameAlg other than TPM_ALG_NULL.
+If the first two octets of keySign are not a valid hash algorithm, the TPM shall return TPM_RC_HASH. If
+the remainder of the Name is not the size of the indicated digest, the TPM shall return TPM_RC_SIZE.
+The TPM validates that the approvedPolicy matches the current value of policySession→policyDigest and
+if not, shall return TPM_RC_VALUE.
+The TPM then validates that the parameters to TPM2_PolicyAuthorize() match the values used to
+generate the ticket. If so, the TPM will reset policySession→policyDigest to a Zero Digest. Then it will
+create a TPM2B_NAME (keyName) using keySign and update policySession→policyDigest with
+PolicyUpdate() (see 25.2.3).
+
+PolicyUpdate(TPM_CC_PolicyAuthorize, keyName, policyRef)
+
+(35)
+
+If the ticket is not valid, the TPM shall return TPM_RC_POLICY.
+If policySession is a trial session, policySession→policyDigest is extended as if the ticket is valid without
+actual verification.
+NOTE
+
+The unmarshaling process requires that a proper TPMT_TK_VERIFIED be provided for checkTicket
+but it may be a NULL Ticket.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 287
+October 31, 2013
+
+ Part 3: Commands
+
+25.16.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 139 — TPM2_PolicyAuthorize Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyAuthorize
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPM2B_DIGEST
+
+approvedPolicy
+
+digest of the policy being approved
+
+TPM2B_NONCE
+
+policyRef
+
+a policy qualifier
+
+TPM2B_NAME
+
+keySign
+
+Name of a key that can sign a policy addition
+
+TPMT_TK_VERIFIED
+
+checkTicket
+
+ticket validating that approvedPolicy and policyRef were
+signed by keySign
+
+Table 140 — TPM2_PolicyAuthorize Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 288
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.16.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyAuthorize_fp.h"
+#include "Policy_spt_fp.h"
+Error Returns
+TPM_RC_HASH
+
+hash algorithm in keyName is not supported
+
+TPM_RC_SIZE
+
+keyName is not the correct size for its hash algorithm
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+Meaning
+
+the current policyDigest of policySession does not match
+approvedPolicy; or checkTicket doesn't match the provided values
+
+TPM_RC
+TPM2_PolicyAuthorize(
+PolicyAuthorize_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM2B_DIGEST
+HASH_STATE
+TPMT_TK_VERIFIED
+TPM_ALG_ID
+UINT16
+
+*session;
+authHash;
+hashState;
+ticket;
+hashAlg;
+digestSize;
+
+)
+{
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Extract from the Name of the key, the algorithm used to compute it's Name
+hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
+// 'keySign' parameter needs to use a supported hash algorithm, otherwise
+// can't tell how large the digest should be
+digestSize = CryptGetHashDigestSize(hashAlg);
+if(digestSize == 0)
+return TPM_RC_HASH + RC_PolicyAuthorize_keySign;
+if(digestSize != (in->keySign.t.size - 2))
+return TPM_RC_SIZE + RC_PolicyAuthorize_keySign;
+//If this is a trial policy, skip all validations
+if(session->attributes.isTrialPolicy == CLEAR)
+{
+// Check that "approvedPolicy" matches the current value of the
+// policyDigest in policy session
+if(!Memory2BEqual(&session->u2.policyDigest.b,
+&in->approvedPolicy.b))
+return TPM_RC_VALUE + RC_PolicyAuthorize_approvedPolicy;
+// Validate ticket TPMT_TK_VERIFIED
+// Compute aHash. The authorizing object sign a digest
+// aHash := hash(approvedPolicy || policyRef).
+// Start hash
+authHash.t.size = CryptStartHash(hashAlg, &hashState);
+// add approvedPolicy
+CryptUpdateDigest2B(&hashState, &in->approvedPolicy.b);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 289
+October 31, 2013
+
+ Part 3: Commands
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+
+Trusted Platform Module Library
+
+// add policyRef
+CryptUpdateDigest2B(&hashState, &in->policyRef.b);
+// complete hash
+CryptCompleteHash2B(&hashState, &authHash.b);
+// re-compute TPMT_TK_VERIFIED
+TicketComputeVerified(in->checkTicket.hierarchy, &authHash,
+&in->keySign, &ticket);
+// Compare ticket digest. If not match, return error
+if(!Memory2BEqual(&in->checkTicket.digest.b, &ticket.digest.b))
+return TPM_RC_VALUE+ RC_PolicyAuthorize_checkTicket;
+}
+// Internal Data Update
+// Set policyDigest to zero digest
+MemorySet(session->u2.policyDigest.t.buffer, 0,
+session->u2.policyDigest.t.size);
+// Update policyDigest
+PolicyContextUpdate(TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef,
+NULL, 0, session);
+return TPM_RC_SUCCESS;
+}
+
+Page 290
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.17 TPM2_PolicyAuthValue
+25.17.1
+
+General Description
+
+This command allows a policy to be bound to the authorization value of the authorized object.
+When this command completes successfully, policySession→isAuthValueNeeded is SET to indicate that
+the authValue will be included in hmacKey when the authorization HMAC is computed for this session.
+Additionally, policySession→isPasswordNeeded will be CLEAR.
+NOTE
+
+If a policy does not use this command, then the hmacKey for the authorized command would only
+use sessionKey. If sessionKey is not present, then the hmacKey is an Empty Buffer and no HMAC
+would be computed.
+
+If successful, policySession→policyDigest will be updated with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyAuthValue)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+(36)
+
+Page 291
+October 31, 2013
+
+ Part 3: Commands
+
+25.17.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 141 — TPM2_PolicyAuthValue Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyAuthValue
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+Table 142 — TPM2_PolicyAuthValue Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 292
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.17.3
+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
+33
+34
+35
+36
+37
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyAuthValue_fp.h"
+#include "Policy_spt_fp.h"
+
+TPM_RC
+TPM2_PolicyAuthValue(
+PolicyAuthValue_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyAuthValue;
+hashState;
+
+)
+{
+
+// Internal Data Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue)
+//
+Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// complete the hash and get the results
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// update isAuthValueNeeded bit in the session context
+session->attributes.isAuthValueNeeded = SET;
+session->attributes.isPasswordNeeded = CLEAR;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 293
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.18 TPM2_PolicyPassword
+25.18.1
+
+General Description
+
+This command allows a policy to be bound to the authorization value of the authorized object.
+When this command completes successfully, policySession→isPasswordNeeded is SET to indicate that
+authValue of the authorized object will be checked when the session is used for authorization. The caller
+will provide the authValue in clear text in the hmac parameter of the authorization. The comparison of
+hmac to authValue is performed as if the authorization is a password.
+NOTE 1
+
+The parameter field in the policy session where the authorization value is provided is called hmac. If
+TPM2_PolicyPassword() is part of the sequence, then the field will contain a password and not an
+HMAC.
+
+If successful, policySession→policyDigest will be updated with
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyAuthValue)
+NOTE 2
+
+(37)
+
+This is the same extend value as used with TPM2_PolicyAuthValue so that the evaluation may be
+done using either an HMAC or a password with no change to the authPolicy of the object. The
+reason that two commands are present is to indicate to the TPM if the hmac field in the authorization
+will contain an HMAC or a password value.
+
+When this command is successful, policySession→isAuthValueNeeded will be CLEAR.
+
+Page 294
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.18.2
+
+Part 3: Commands
+
+Command and Response
+Table 143 — TPM2_PolicyPassword Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyPassword
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+Table 144 — TPM2_PolicyPassword Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 295
+October 31, 2013
+
+ Part 3: Commands
+
+25.18.3
+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
+33
+34
+35
+36
+37
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyPassword_fp.h"
+#include "Policy_spt_fp.h"
+
+TPM_RC
+TPM2_PolicyPassword(
+PolicyPassword_In
+
+*in
+
+// IN: input parameter list
+
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyAuthValue;
+hashState;
+
+)
+{
+
+// Internal Data Update
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+// Update isPasswordNeeded bit
+session->attributes.isPasswordNeeded = SET;
+session->attributes.isAuthValueNeeded = CLEAR;
+return TPM_RC_SUCCESS;
+}
+
+Page 296
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+25.19 TPM2_PolicyGetDigest
+25.19.1
+
+General Description
+
+This command returns the current policyDigest of the session. This command allows the TPM to be used
+to perform the actions required to pre-compute the authPolicy for an object.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 297
+October 31, 2013
+
+ Part 3: Commands
+
+25.19.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 145 — TPM2_PolicyGetDigest Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyGetDigest
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session
+Auth Index: None
+
+Table 146 — TPM2_PolicyGetDigest Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_DIGEST
+
+policyDigest
+
+Page 298
+October 31, 2013
+
+the current value of the policySession→policyDigest
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.19.3
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyGetDigest_fp.h"
+
+TPM_RC
+TPM2_PolicyGetDigest(
+PolicyGetDigest_In
+PolicyGetDigest_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+SESSION
+
+*session;
+
+// Command Output
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+out->policyDigest = session->u2.policyDigest;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 299
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+25.20 TPM2_PolicyNvWritten
+25.20.1
+
+General Description
+
+This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a deferred
+assertion. Values are stored in the policy session context and checked when the policy is used for
+authorization.
+If policySession→checkNVWritten is CLEAR, it is SET and policySession→nvWrittenState is set to
+writtenSet.
+If policySession→checkNVWritten is SET, the TPM will return TPM_RC_VALUE if
+policySession→nvWrittenState and writtenSet are not the same.
+If the TPM does not return and error, it will update policySession→policyDigest by
+
+policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNvWritten || writtenSet)
+
+(38)
+
+When the policy session is used to authorize a command, the TPM will fail the command if
+policySession→checkNVWritten is SET and nvIndex→attributes→TPMA_NV_WRITTEN does not match
+policySession→nvWrittenState.
+NOTE
+
+A typical use case is a simple policy for the first write during manufacturing provisioning that would
+require TPMA_NV_WRITTEN CLEAR and a more complex policy for later use that would require
+TPMA_NV_WRITTEN SET.
+
+Page 300
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+25.20.2
+
+Part 3: Commands
+
+Command and Response
+Table 147 — TPM2_PolicyNvWritten Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+Tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PolicyNVWritten
+
+TPMI_SH_POLICY
+
+policySession
+
+handle for the policy session being extended
+Auth Index: None
+
+TPMI_YES_NO
+
+writtenSet
+
+YES if NV Index is required to have been written
+NO if NV Index is required not to have been written
+
+Table 148 — TPM2_PolicyNvWritten Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+Tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 301
+October 31, 2013
+
+ Part 3: Commands
+
+25.20.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "PolicyNvWritten_fp.h"
+
+Make an NV Index policy dependent on the state of the TPMA_NV_WRITTEN attribute of the index.
+Error Returns
+TPM_RC_VALUE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+Meaning
+a conflicting request for the attribute has already been processed
+
+TPM_RC
+TPM2_PolicyNvWritten(
+PolicyNvWritten_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+SESSION
+TPM_CC
+HASH_STATE
+
+*session;
+commandCode = TPM_CC_PolicyNvWritten;
+hashState;
+
+// Input Validation
+// Get pointer to the session structure
+session = SessionGet(in->policySession);
+// If already set is this a duplicate (the same setting)? If it
+// is a conflicting setting, it is an error
+if(session->attributes.checkNvWritten == SET)
+{
+if((
+(session->attributes.nvWrittenState == SET)
+!= (in->writtenSet == YES)))
+return TPM_RC_VALUE + RC_PolicyNvWritten_writtenSet;
+}
+// Internal Data Update
+// Set session attributes so that the NV Index needs to be checked
+session->attributes.checkNvWritten = SET;
+session->attributes.nvWrittenState = (in->writtenSet == YES);
+// Update policy hash
+// policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNvWritten
+//
+|| writtenSet)
+// Start hash
+CryptStartHash(session->authHashAlg, &hashState);
+// add old digest
+CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
+// add commandCode
+CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
+// add the byte of writtenState
+CryptUpdateDigestInt(&hashState, sizeof(TPMI_YES_NO), &in->writtenSet);
+// complete the digest
+CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
+return TPM_RC_SUCCESS;
+}
+
+Page 302
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Part 3: Commands
+
+Published
+Copyright © TCG 2006-2013
+
+Page 303
+October 31, 2013
+
+ Part 3: Commands
+
+26
+
+Trusted Platform Module Library
+
+Hierarchy Commands
+
+26.1
+
+TPM2_CreatePrimary
+
+26.1.1 General Description
+This command is used to create a Primary Object under one of the Primary Seeds or a Temporary Object
+under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for the object to be created.
+The command will create and load a Primary Object. The sensitive area is not returned.
+NOTE:
+
+Since the sensitive data is not returned, the key cannot be reloaded.
+persistent or it can be recreated.
+
+It can either be made
+
+Any type of object and attributes combination that is allowed by TPM2_Create() may be created by this
+command. The constraints on templates and parameters are the same as TPM2_Create() except that a
+Primary Storage Key and a Temporary Storage Key are not constrained to use the algorithms of their
+parents.
+For setting of the attributes of the created object, fixedParent, fixedTPM, userWithAuth, adminWithPolicy,
+encrypt, and restricted are implied to be SET in the parent (a Permanent Handle). The remaining
+attributes are implied to be CLEAR.
+The TPM will derive the object from the Primary Seed indicated in primaryHandle using an approved
+KDF. All of the bits of the template are used in the creation of the Primary Key. Methods for creating a
+Primary Object from a Primary Seed are described in Part 1 of this specification and implemented in Part
+4.
+If this command is called multiple times with the same inPublic parameter, inSensitive.data, and Primary
+Seed, the TPM shall produce the same Primary Object.
+NOTE
+
+If the Primary Seed is changed, the Primary Objects generated with the new seed shall be
+statistically unique even if the parameters of the call are the same.
+
+This command requires authorization. Authorization for a Primary Object attached to the Platform Primary
+Seed (PPS) shall be provided by platformAuth or platformPolicy. Authorization for a Primary Object
+attached to the Storage Primary Seed (SPS) shall be provided by ownerAuth or ownerPolicy.
+Authorization for a Primary Key attached to the Endorsement Primary Seed (EPS) shall be provided by
+endorsementAuth or endorsementPolicy.
+
+Page 304
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.1.2 Command and Response
+Table 149 — TPM2_CreatePrimary Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_CreatePrimary
+
+TPMI_RH_HIERARCHY+
+
+@primaryHandle
+
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER,
+TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_SENSITIVE_CREATE
+
+inSensitive
+
+the sensitive data, see Part 1 Sensitive Values
+
+TPM2B_PUBLIC
+
+inPublic
+
+the public template
+
+TPM2B_DATA
+
+outsideInfo
+
+data that will be included in the creation data for this
+object to provide permanent, verifiable linkage between
+this object and some object owner data
+
+TPML_PCR_SELECTION
+
+creationPCR
+
+PCR that will be used in creation data
+
+Table 150 — TPM2_CreatePrimary Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM_HANDLE
+
+objectHandle
+
+Handle for created Primary Object
+
+TPM2B_PUBLIC
+
+outPublic
+
+the public portion of the created object
+
+TPM2B_CREATION_DATA
+
+creationData
+
+contains a TPMT_CREATION_DATA
+
+TPM2B_DIGEST
+
+creationHash
+
+digest of creationData using nameAlg of outPublic
+
+TPMT_TK_CREATION
+
+creationTicket
+
+ticket used by TPM2_CertifyCreation() to validate that
+the creation data was produced by the TPM
+
+TPM2B_NAME
+
+name
+
+the name of the created object
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 305
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.1.3 Detailed Actions
+1
+2
+3
+4
+
+#include
+#include
+#include
+#include
+
+"InternalRoutines.h"
+"CreatePrimary_fp.h"
+"Object_spt_fp.h"
+<Platform.h>
+
+Error Returns
+TPM_RC_ATTRIBUTES
+
+sensitiveDataOrigin is CLEAR when 'sensitive. data' is an Empty
+Buffer, or is SET when 'sensitive. data' is not empty; fixedTPM,
+fixedParent, or encryptedDuplication attributes are inconsistent
+between themselves or with those of the parent object; inconsistent
+restricted, decrypt and sign attributes; attempt to inject sensitive data
+for an asymmetric key; attempt to create a symmetric cipher key that
+is not a decryption key
+
+TPM_RC_KDF
+
+incorrect KDF specified for decrypting keyed hash object
+
+TPM_RC_OBJECT_MEMORY
+
+there is no free slot for the object
+
+TPM_RC_SCHEME
+
+inconsistent attributes decrypt, sign, restricted and key's scheme ID;
+or hash algorithm is inconsistent with the scheme ID for keyed hash
+object
+
+TPM_RC_SIZE
+
+size of public auth policy or sensitive auth value does not match
+digest size of the name algorithm sensitive data size for the keyed
+hash object is larger than is allowed for the scheme
+
+TPM_RC_SYMMETRIC
+
+a storage key with no symmetric algorithm specified; or non-storage
+key with symmetric algorithm different from TPM_ALG_NULL
+
+TPM_RC_TYPE
+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
+33
+
+Meaning
+
+unknown object type;
+
+TPM_RC
+TPM2_CreatePrimary(
+CreatePrimary_In
+CreatePrimary_Out
+)
+{
+// Local variables
+TPM_RC
+TPMT_SENSITIVE
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+result = TPM_RC_SUCCESS;
+sensitive;
+
+// Input Validation
+// The sensitiveDataOrigin attribute must be consistent with the setting of
+// the size of the data object in inSensitive.
+if(
+(in->inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin == SET)
+!= (in->inSensitive.t.sensitive.data.t.size == 0 ))
+// Mismatch between the object attributes and the parameter.
+return TPM_RC_ATTRIBUTES + RC_CreatePrimary_inSensitive;
+// Check attributes in input public area. TPM_RC_ATTRIBUTES, TPM_RC_KDF,
+// TPM_RC_SCHEME, TPM_RC_SIZE, TPM_RC_SYMMETRIC, or TPM_RC_TYPE error may
+// be returned at this point.
+result = PublicAttributesValidation(FALSE, in->primaryHandle,
+&in->inPublic.t.publicArea);
+if(result != TPM_RC_SUCCESS)
+return RcSafeAddToResult(result, RC_CreatePrimary_inPublic);
+// Validate the sensitive area values
+if( MemoryRemoveTrailingZeros(&in->inSensitive.t.sensitive.userAuth)
+> CryptGetHashDigestSize(in->inPublic.t.publicArea.nameAlg))
+
+Page 306
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+
+Part 3: Commands
+
+return TPM_RC_SIZE + RC_CreatePrimary_inSensitive;
+// Command output
+// Generate Primary Object
+// The primary key generation process uses the Name of the input public
+// template to compute the key. The keys are generated from the template
+// before anything in the template is allowed to be changed.
+// A TPM_RC_KDF, TPM_RC_SIZE error may be returned at this point
+result = CryptCreateObject(in->primaryHandle, &in->inPublic.t.publicArea,
+&in->inSensitive.t.sensitive,&sensitive);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Fill in creation data
+FillInCreationData(in->primaryHandle, in->inPublic.t.publicArea.nameAlg,
+&in->creationPCR, &in->outsideInfo, &out->creationData,
+&out->creationHash);
+// Copy public area
+out->outPublic = in->inPublic;
+// Fill in private area for output
+ObjectComputeName(&(out->outPublic.t.publicArea), &out->name);
+// Compute creation ticket
+TicketComputeCreation(EntityGetHierarchy(in->primaryHandle), &out->name,
+&out->creationHash, &out->creationTicket);
+// Create a internal object. A TPM_RC_OBJECT_MEMORY error may be returned
+// at this point.
+result = ObjectLoad(in->primaryHandle, &in->inPublic.t.publicArea, &sensitive,
+&out->name, in->primaryHandle, TRUE, &out->objectHandle);
+return result;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 307
+October 31, 2013
+
+ Part 3: Commands
+
+26.2
+
+Trusted Platform Module Library
+
+TPM2_HierarchyControl
+
+26.2.1 General Description
+This command enables and disables use of a hierarchy and its associated NV storage. The command
+allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the proper authorization is
+provided.
+This command may be used to CLEAR phEnable and phEnableNV if platformAuth/platformPolicy is
+provided. phEnable may not be SET using this command.
+This command may be used to CLEAR shEnable if either platformAuth/platformPolicy
+ownerAuth/ownerPolicy is provided. shEnable may be SET if platformAuth/platformPolicy is provided.
+
+or
+
+This command may be used to CLEAR ehEnable if either platformAuth/platformPolicy or
+endorsementAuth/endorsementPolicy is provided. ehEnable may be SET if platformAuth/platformPolicy is
+provided.
+When this command is used to CLEAR phEnable, shEnable, or ehEnable, the TPM will disable use of
+any persistent entity associated with the disabled hierarchy and will flush any transient objects associated
+with the disabled hierarchy.
+When this command is used to CLEAR shEnable, the TPM will disable access to any NV index that has
+TPMA_NV_PLATFORMCREATE CLEAR (indicating that the NV Index was defined using ownerAuth). As
+long as shEnable is CLEAR, the TPM will return an error in response to any command that attempts to
+operate upon an NV index that has TPMA_NV_PLATFORMCREATE CLEAR.
+When this command is used to CLEAR phEnableNV, the TPM will disable access to any NV index that
+has TPMA_NV_PLATFORMCREATE SET (indicating that the NV Index was defined using platformAuth).
+As long as phEnableNV is CLEAR, the TPM will return an error in response to any command that
+attempts to operate upon an NV index that has TPMA_NV_PLATFORMCREATE SET.
+
+Page 308
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.2.2 Command and Response
+Table 151 — TPM2_HierarchyControl Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HierarchyControl {NV E}
+
+TPMI_RH_HIERARCHY
+
+@authHandle
+
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER or
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_ENABLES
+
+enable
+
+the enable being modified
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER,
+TPM_RH_PLATFORM, or TPM_RH_PLATFORM_NV
+
+TPMI_YES_NO
+
+state
+
+YES if the enable should be SET, NO if the enable
+should be CLEAR
+
+Table 152 — TPM2_HierarchyControl Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 309
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "HierarchyControl_fp.h"
+Error Returns
+TPM_RC_AUTH_TYPE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+authHandle is not applicable to hierarchy in its current state
+
+TPM_RC
+TPM2_HierarchyControl(
+HierarchyControl_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+BOOL
+BOOL
+
+result;
+select = (in->state == YES);
+*selected = NULL;
+
+// Input Validation
+switch(in->enable)
+{
+// Platform hierarchy has to be disabled by platform auth
+// If the platform hierarchy has already been disabled, only a reboot
+// can enable it again
+case TPM_RH_PLATFORM:
+case TPM_RH_PLATFORM_NV:
+if(in->authHandle != TPM_RH_PLATFORM)
+return TPM_RC_AUTH_TYPE;
+break;
+// ShEnable may be disabled if PlatformAuth/PlatformPolicy or
+// OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it
+// may only be enabled if PlatformAuth/PlatformPolicy is provided.
+case TPM_RH_OWNER:
+if(
+in->authHandle != TPM_RH_PLATFORM
+&& in->authHandle != TPM_RH_OWNER)
+return TPM_RC_AUTH_TYPE;
+if(
+gc.shEnable == FALSE && in->state == YES
+&& in->authHandle != TPM_RH_PLATFORM)
+return TPM_RC_AUTH_TYPE;
+break;
+// EhEnable may be disabled if either PlatformAuth/PlatformPolicy or
+// EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled,
+// then it may only be enabled if PlatformAuth/PlatformPolicy is
+// provided.
+case TPM_RH_ENDORSEMENT:
+if(
+in->authHandle != TPM_RH_PLATFORM
+&& in->authHandle != TPM_RH_ENDORSEMENT)
+return TPM_RC_AUTH_TYPE;
+if(
+gc.ehEnable == FALSE && in->state == YES
+&& in->authHandle != TPM_RH_PLATFORM)
+return TPM_RC_AUTH_TYPE;
+break;
+default:
+pAssert(FALSE);
+break;
+}
+// Internal Data Update
+
+Page 310
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
+Part 3: Commands
+
+// Enable or disable the selected hierarchy
+// Note: the authorization processing for this command may keep these
+// command actions from being executed. For example, if phEnable is
+// CLEAR, then platformAuth cannot be used for authorization. This
+// means that would not be possible to use platformAuth to change the
+// state of phEnable from CLEAR to SET.
+// If it is decided that platformPolicy can still be used when phEnable
+// is CLEAR, then this code could SET phEnable when proper platform
+// policy is provided.
+switch(in->enable)
+{
+case TPM_RH_OWNER:
+selected = &gc.shEnable;
+break;
+case TPM_RH_ENDORSEMENT:
+selected = &gc.ehEnable;
+break;
+case TPM_RH_PLATFORM:
+selected = &g_phEnable;
+break;
+case TPM_RH_PLATFORM_NV:
+selected = &gc.phEnableNV;
+break;
+default:
+pAssert(FALSE);
+break;
+}
+if(selected != NULL && *selected != select)
+{
+// Before changing the internal state, make sure that NV is available.
+// Only need to update NV if changing the orderly state
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// state is changing and NV is available so modify
+*selected = select;
+// If a hierarchy was just disabled, flush it
+if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV)
+// Flush hierarchy
+ObjectFlushHierarchy(in->enable);
+// orderly state should be cleared because of the update to state clear data
+// This gets processed in ExecuteCommand() on the way out.
+g_clearOrderly = TRUE;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 311
+October 31, 2013
+
+ Part 3: Commands
+
+26.3
+
+Trusted Platform Module Library
+
+TPM2_SetPrimaryPolicy
+
+26.3.1 General Description
+This command allows setting of the authorization policy for the platform hierarchy (platformPolicy), the
+storage hierarchy (ownerPolicy), and the endorsement hierarchy (endorsementPolicy).
+The command requires an authorization session. The session shall use the current authValue or satisfy
+the current authPolicy for the referenced hierarchy.
+The policy that is changed is the policy associated with authHandle.
+If the enable associated with authHandle is not SET, then the associated authorization values (authValue
+or authPolicy) may not be used.
+
+Page 312
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.3.2 Command and Response
+Table 153 — TPM2_SetPrimaryPolicy Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SetPrimaryPolicy {NV}
+
+TPMI_RH_HIERARCHY
+
+@authHandle
+
+TPM_RH_ENDORSEMENT, TPM_RH_OWNER or
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_DIGEST
+
+authPolicy
+
+an authorization policy digest; may be the Empty Buffer
+If hashAlg is TPM_ALG_NULL, then this shall be an
+Empty Buffer.
+
+TPMI_ALG_HASH+
+
+hashAlg
+
+the hash algorithm to use for the policy
+If the authPolicy is an Empty Buffer, then this field shall
+be TPM_ALG_NULL.
+
+Table 154 — TPM2_SetPrimaryPolicy Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 313
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "SetPrimaryPolicy_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+size of input authPolicy is not consistent with input hash algorithm
+
+TPM_RC
+TPM2_SetPrimaryPolicy(
+SetPrimaryPolicy_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input Validation
+// Check the authPolicy consistent with hash algorithm
+if(
+in->authPolicy.t.size != 0
+&& in->authPolicy.t.size != CryptGetHashDigestSize(in->hashAlg))
+return TPM_RC_SIZE + RC_SetPrimaryPolicy_authPolicy;
+// The command need NV update for OWNER and ENDORSEMENT hierarchy, and
+// might need orderlyState update for PLATFROM hierarchy.
+// Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
+// error may be returned at this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+// Set hierarchy policy
+switch(in->authHandle)
+{
+case TPM_RH_OWNER:
+gp.ownerAlg = in->hashAlg;
+gp.ownerPolicy = in->authPolicy;
+NvWriteReserved(NV_OWNER_ALG, &gp.ownerAlg);
+NvWriteReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
+break;
+case TPM_RH_ENDORSEMENT:
+gp.endorsementAlg = in->hashAlg;
+gp.endorsementPolicy = in->authPolicy;
+NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
+NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
+break;
+case TPM_RH_PLATFORM:
+gc.platformAlg = in->hashAlg;
+gc.platformPolicy = in->authPolicy;
+// need to update orderly state
+g_clearOrderly = TRUE;
+break;
+default:
+pAssert(FALSE);
+break;
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 314
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+26.4
+
+Part 3: Commands
+
+TPM2_ChangePPS
+
+26.4.1 General Description
+This replaces the current PPS with a value from the RNG and sets platformPolicy to the default
+initialization value (the Empty Buffer).
+NOTE 1
+
+A policy that is the Empty Buffer can match no policy.
+
+NOTE 2
+
+platformAuth is not changed.
+
+All loaded transient and persistent objects in the Platform hierarchy are flushed.
+Saved contexts in the Platform hierarchy that were created under the old PPS will no longer be able to be
+loaded.
+The policy hash algorithm for PCR is reset to TPM_ALG_NULL.
+This command does not clear any NV Index values.
+NOTE 3
+
+Index values belonging to the Platform are preserved because the indexes may have configuration
+information that will be the same after the PPS changes. The Platform may remove the indexes that
+are no longer needed using TPM2_NV_UndefineSpace().
+
+This command requires platformAuth.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 315
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.4.2 Command and Response
+Table 155 — TPM2_ChangePPS Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ChangePPS {NV E}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+Description
+
+Table 156 — TPM2_ChangePPS Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 316
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.4.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+#include "InternalRoutines.h"
+#include "ChangePPS_fp.h"
+
+TPM_RC
+TPM2_ChangePPS(
+ChangePPS_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+TPM_RC
+
+i;
+result;
+
+// Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
+// error may be returned at this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input parameter is not reference in command action
+in = NULL;
+// Internal Data Update
+// Reset platform hierarchy seed from RNG
+CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.PPSeed.t.buffer);
+// Create a new phProof value from RNG to prevent the saved platform
+// hierarchy contexts being loaded
+CryptGenerateRandom(PROOF_SIZE, gp.phProof.t.buffer);
+// Set platform authPolicy to null
+gc.platformAlg = TPM_ALG_NULL;
+gc.platformPolicy.t.size = 0;
+// Flush loaded object in platform hierarchy
+ObjectFlushHierarchy(TPM_RH_PLATFORM);
+// Flush platform evict object and index in NV
+NvFlushHierarchy(TPM_RH_PLATFORM);
+// Save hierarchy changes to NV
+NvWriteReserved(NV_PP_SEED, &gp.PPSeed);
+NvWriteReserved(NV_PH_PROOF, &gp.phProof);
+// Re-initialize PCR policies
+for(i = 0; i < NUM_POLICY_PCR_GROUP; i++)
+{
+gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
+gp.pcrPolicies.policy[i].t.size = 0;
+}
+NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
+// orderly state should be cleared because of the update to state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 317
+October 31, 2013
+
+ Part 3: Commands
+
+26.5
+
+Trusted Platform Module Library
+
+TPM2_ChangeEPS
+
+26.5.1 General Description
+This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to
+their default initialization values: ehEnable is SET, endorsementAuth and endorsementPolicy both equal
+to the Empty Buffer. It will flush any loaded objects in the EPS hierarchy and not allow objects in the
+hierarchy associated with the previous EPS to be loaded.
+NOTE
+
+In the reference implementation, ehProof is a non-volatile value from the RNG. It is allowed that the
+ehProof be generated by a KDF using both the EPS and SPS as inputs. If generated with a KDF, the
+ehProof can be generated on an as-needed basis or made a non-volatile value.
+
+This command requires platformAuth.
+
+Page 318
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.5.2 Command and Response
+Table 157 — TPM2_ChangeEPS Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ChangeEPS {NV E}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+Description
+
+Table 158 — TPM2_ChangeEPS Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 319
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.5.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+#include "InternalRoutines.h"
+#include "ChangeEPS_fp.h"
+
+TPM_RC
+TPM2_ChangeEPS(
+ChangeEPS_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input parameter is not reference in command action
+in = NULL;
+// Internal Data Update
+// Reset endorsement hierarchy seed from RNG
+CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.EPSeed.t.buffer);
+// Create new ehProof value from RNG
+CryptGenerateRandom(PROOF_SIZE, gp.ehProof.t.buffer);
+// Enable endorsement hierarchy
+gc.ehEnable = TRUE;
+// set authValue buffer to zeros
+MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size);
+// Set endorsement authValue to null
+gp.endorsementAuth.t.size = 0;
+// Set endorsement authPolicy to null
+gp.endorsementAlg = TPM_ALG_NULL;
+gp.endorsementPolicy.t.size = 0;
+// Flush loaded object in endorsement hierarchy
+ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
+// Flush evict object of endorsement hierarchy stored in NV
+NvFlushHierarchy(TPM_RH_ENDORSEMENT);
+// Save hierarchy changes to NV
+NvWriteReserved(NV_EP_SEED, &gp.EPSeed);
+NvWriteReserved(NV_EH_PROOF, &gp.ehProof);
+NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
+NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
+NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
+// orderly state should be cleared because of the update to state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 320
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+26.6
+
+Part 3: Commands
+
+TPM2_Clear
+
+26.6.1 General Description
+This command removes all TPM context associated with a specific Owner.
+The clear operation will:
+
+
+flush loaded objects (persistent and volatile) in the Storage and Endorsement hierarchies;
+
+
+
+delete any NV Index with TPMA_NV_PLATFORMCREATE == CLEAR;
+
+
+
+change the SPS to a new value from the TPM’s random number generator (RNG),
+
+
+
+change shProof and ehProof,
+NOTE
+
+The proof values may be set from the RNG or derived from the associated new Primary Seed. If
+derived from the Primary Seeds, the derivation of ehProof shall use both the SPS and EPS. The
+computation shall use the SPS as an HMAC key and the derived value may then be a parameter
+in a second HMAC in which the EPS is the HMAC key. The reference design uses values from
+the RNG.
+
+
+
+SET shEnable and ehEnable;
+
+
+
+set ownerAuth, endorsementAuth, and lockoutAuth to the Empty Buffer;
+
+
+
+set ownerPolicy and endorsementPolicy to the Empty Buffer;
+
+
+
+set Clock to zero;
+
+
+
+set resetCount to zero;
+
+
+
+set restartCount to zero; and
+
+
+
+set Safe to YES.
+
+This command requires platformAuth or lockoutAuth. If TPM2_ClearControl() has disabled this command,
+the TPM shall return TPM_RC_DISABLED.
+If this command is authorized using lockoutAuth, the HMAC in the response shall use the new
+lockoutAuth value (that is, the Empty Buffer) when computing response HMAC.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 321
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.6.2 Command and Response
+Table 159 — TPM2_Clear Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_Clear {NV E}
+
+TPMI_RH_CLEAR
+
+@authHandle
+
+TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+Description
+
+Table 160 — TPM2_Clear Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 322
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.6.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "Clear_fp.h"
+Error Returns
+TPM_RC_DISABLED
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+
+Meaning
+Clear command has been disabled
+
+TPM_RC
+TPM2_Clear(
+Clear_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input parameter is not reference in command action
+in = NULL;
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// If Clear command is disabled, return an error
+if(gp.disableClear)
+return TPM_RC_DISABLED;
+// Internal Data Update
+// Reset storage hierarchy seed from RNG
+CryptGenerateRandom(PRIMARY_SEED_SIZE, gp.SPSeed.t.buffer);
+// Create new shProof and ehProof value from RNG
+CryptGenerateRandom(PROOF_SIZE, gp.shProof.t.buffer);
+CryptGenerateRandom(PROOF_SIZE, gp.ehProof.t.buffer);
+// Enable storage and endorsement hierarchy
+gc.shEnable = gc.ehEnable = TRUE;
+// set the authValue buffers to zero
+MemorySet(gp.ownerAuth.t.buffer, 0, gp.ownerAuth.t.size);
+MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size);
+MemorySet(gp.lockoutAuth.t.buffer, 0, gp.lockoutAuth.t.size);
+// Set storage, endorsement and lockout authValue to null
+gp.ownerAuth.t.size = gp.endorsementAuth.t.size = gp.lockoutAuth.t.size = 0;
+// Set storage and endorsement authPolicy to null
+gp.ownerAlg = gp.endorsementAlg = TPM_ALG_NULL;
+gp.ownerPolicy.t.size = gp.endorsementPolicy.t.size = 0;
+// Flush loaded object in storage and endorsement hierarchy
+ObjectFlushHierarchy(TPM_RH_OWNER);
+ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
+// Flush owner and endorsement object and owner index in NV
+NvFlushHierarchy(TPM_RH_OWNER);
+NvFlushHierarchy(TPM_RH_ENDORSEMENT);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 323
+October 31, 2013
+
+ Part 3: Commands
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+
+Trusted Platform Module Library
+
+// Save hierarchy changes to NV
+NvWriteReserved(NV_SP_SEED, &gp.SPSeed);
+NvWriteReserved(NV_SH_PROOF, &gp.shProof);
+NvWriteReserved(NV_EH_PROOF, &gp.ehProof);
+NvWriteReserved(NV_OWNER_AUTH, &gp.ownerAuth);
+NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
+NvWriteReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
+NvWriteReserved(NV_OWNER_ALG, &gp.ownerAlg);
+NvWriteReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
+NvWriteReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
+NvWriteReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
+// Initialize dictionary attack parameters
+DAPreInstall_Init();
+// Reset clock
+go.clock = 0;
+go.clockSafe = YES;
+// Update the DRBG state whenever writing orderly state to NV
+CryptDrbgGetPutState(GET_STATE);
+NvWriteReserved(NV_ORDERLY_DATA, &go);
+// Reset counters
+gp.resetCount = gr.restartCount = gr.clearCount = 0;
+gp.auditCounter = 0;
+NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
+NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
+// orderly state should be cleared because of the update to state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 324
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+26.7
+
+Part 3: Commands
+
+TPM2_ClearControl
+
+26.7.1 General Description
+TPM2_ClearControl() disables and enables the execution of TPM2_Clear().
+The TPM will SET the TPM’s TPMA_PERMANENT.disableClear attribute if disable is YES and will
+CLEAR the attribute if disable is NO. When the attribute is SET, TPM2_Clear() may not be executed.
+NOTE
+
+This is to simplify the logic of TPM2_Clear(). TPM2_ClearControl() can be called using platformAuth
+to CLEAR the disableClear attribute and then execute TPM2_Clear().
+
+LockoutAuth may be used to SET disableClear but not to CLEAR it.
+PlatformAuth may be used to SET or CLEAR disableClear.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 325
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.7.2 Command and Response
+Table 161 — TPM2_ClearControl Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ClearControl {NV}
+
+TPMI_RH_CLEAR
+
+@auth
+
+TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPMI_YES_NO
+
+disable
+
+YES if the disableOwnerClear flag is to be SET, NO if
+the flag is to be CLEAR.
+
+Table 162 — TPM2_ClearControl Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 326
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.7.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "ClearControl_fp.h"
+Error Returns
+TPM_RC_AUTH_FAIL
+
+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
+33
+
+Meaning
+authorization is not properly given
+
+TPM_RC
+TPM2_ClearControl(
+ClearControl_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE
+if(in->auth == TPM_RH_LOCKOUT && in->disable == NO)
+return TPM_RC_AUTH_FAIL;
+// Internal Data Update
+if(in->disable == YES)
+gp.disableClear = TRUE;
+else
+gp.disableClear = FALSE;
+// Record the change to NV
+NvWriteReserved(NV_DISABLE_CLEAR, &gp.disableClear);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 327
+October 31, 2013
+
+ Part 3: Commands
+
+26.8
+
+Trusted Platform Module Library
+
+TPM2_HierarchyChangeAuth
+
+26.8.1 General Description
+This command allows the authorization secret for a hierarchy or lockout to be changed using the current
+authorization value as the command authorization.
+If authHandle is TPM_RH_PLATFORM, then platformAuth is changed. If authHandle is
+TPM_RH_OWNER, then ownerAuth is changed. If authHandle is TPM_RH_ENDORSEMENT, then
+endorsementAuth is changed. If authHandle is TPM_RH_LOCKOUT, then lockoutAuth is changed.
+If authHandle is TPM_RH_PLATFORM, then Physical Presence may need to be asserted for this
+command to succeed (see 28.2, “TPM2_PP_Commands”).
+The authorization value may be no larger than the digest produced by the hash algorithm used for context
+integrity.
+EXAMPLE
+
+If SHA384 is used in the computation of the integrity values for saved contexts, then the largest
+authorization value is 48 octets.
+
+Page 328
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+26.8.2 Command and Response
+Table 163 — TPM2_HierarchyChangeAuth Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_HierarchyChangeAuth {NV}
+
+TPMI_RH_HIERARCHY_AUTH
+
+@authHandle
+
+TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT,
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_AUTH
+
+newAuth
+
+new authorization value
+
+Table 164 — TPM2_HierarchyChangeAuth Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 329
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+26.8.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "HierarchyChangeAuth_fp.h"
+#include "Object_spt_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+newAuth size is greater than that of integrity hash digest
+
+TPM_RC
+TPM2_HierarchyChangeAuth(
+HierarchyChangeAuth_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Make sure the the auth value is a reasonable size (not larger than
+// the size of the digest produced by the integrity hash. The integrity
+// hash is assumed to produce the longest digest of any hash implemented
+// on the TPM.
+if( MemoryRemoveTrailingZeros(&in->newAuth)
+> CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG))
+return TPM_RC_SIZE + RC_HierarchyChangeAuth_newAuth;
+// Set hierarchy authValue
+switch(in->authHandle)
+{
+case TPM_RH_OWNER:
+gp.ownerAuth = in->newAuth;
+NvWriteReserved(NV_OWNER_AUTH, &gp.ownerAuth);
+break;
+case TPM_RH_ENDORSEMENT:
+gp.endorsementAuth = in->newAuth;
+NvWriteReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
+break;
+case TPM_RH_PLATFORM:
+gc.platformAuth = in->newAuth;
+// orderly state should be cleared
+g_clearOrderly = TRUE;
+break;
+case TPM_RH_LOCKOUT:
+gp.lockoutAuth = in->newAuth;
+NvWriteReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
+break;
+default:
+pAssert(FALSE);
+break;
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 330
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+27
+
+Part 3: Commands
+
+Dictionary Attack Functions
+
+27.1
+
+Introduction
+
+A TPM is required to have support for logic that will help prevent a dictionary attack on an authorization
+value. The protection is provided by a counter that increments when a password authorization or an
+HMAC authorization fails. When the counter reaches a predefined value, the TPM will not accept, for
+some time interval, further requests that require authorization and the TPM is in Lockout mode. While the
+TPM is in Lockout mode, the TPM will return TPM_RC_LOCKED if the command requires use of an
+object’s or Index’s authValue unless the authorization applies to an entry in the Platform hierarchy.
+NOTE
+
+Authorizations for objects and NV Index values in the Platform hierarchy are never locked out.
+However, a command that requires multiple authorizations will not be accepted when the TPM is in
+Lockout mode unless all of the authorizations reference objects and indexes in the Platform
+hierarchy.
+
+If the TPM is continuously powered for the duration of newRecoveryTime and no authorization failures
+occur, the authorization failure counter will be decremented by one. This property is called “self-healing.”
+Self-healing shall not cause the count of failed attempts to decrement below zero.
+The count of failed attempts, the lockout interval, and self-healing interval are settable using
+TPM2_DictionaryAttackParameters(). The lockout parameters and the current value of the lockout
+counter can be read with TPM2_GetCapability().
+Dictionary attack protection does not apply to an entity associated with a permanent handle (handle type
+== TPM_HT_PERMANENT).
+27.2
+
+TPM2_DictionaryAttackLockReset
+
+27.2.1 General Description
+This command cancels the effect of a TPM lockout due to a number of successive authorization failures.
+If this command is properly authorized, the lockout counter is set to zero.
+Only one authorization failure is allowed for this command during a lockoutRecovery interval (set using
+TPM2_DictionaryAttackParameters().
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 331
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+27.2.2 Command and Response
+Table 165 — TPM2_DictionaryAttackLockReset Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_DictionaryAttackLockReset {NV}
+
+TPMI_RH_LOCKOUT
+
+@lockHandle
+
+TPM_RH_LOCKOUT
+Auth Index: 1
+Auth Role: USER
+
+Description
+
+Table 166 — TPM2_DictionaryAttackLockReset Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 332
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+27.2.3 Detailed Actions
+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
+
+#include "InternalRoutines.h"
+#include "DictionaryAttackLockReset_fp.h"
+
+TPM_RC
+TPM2_DictionaryAttackLockReset(
+DictionaryAttackLockReset_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input parameter is not reference in command action
+in = NULL;
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+// Set failed tries to 0
+gp.failedTries = 0;
+// Record the changes to NV
+NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 333
+October 31, 2013
+
+ Part 3: Commands
+
+27.3
+
+Trusted Platform Module Library
+
+TPM2_DictionaryAttackParameters
+
+27.3.1 General Description
+This command changes the lockout parameters.
+The command requires lockoutAuth.
+The timeout parameters (newRecoveryTime and lockoutRecovery) indicate values that are measured with
+respect to the Time and not Clock.
+NOTE
+
+Use of Time means that the TPM shall be continuously powered for the duration of a timeout.
+
+If newRecoveryTime is zero, then DA protection is disabled. Authorizations are checked but authorization
+failures will not cause the TPM to enter lockout.
+If newMaxTries is zero, the TPM will be in lockout and use of DA protected entities will be disabled.
+If lockoutRecovery is zero, then the recovery interval is a boot cycle (_TPM_Init followed by
+Startup(CLEAR).
+This command will set the authorization failure count (failedTries) to zero.
+Only one authorization failure is allowed for this command during a lockoutRecovery interval.
+
+Page 334
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+27.3.2 Command and Response
+Table 167 — TPM2_DictionaryAttackParameters Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_DictionaryAttackParameters {NV}
+
+TPMI_RH_LOCKOUT
+
+@lockHandle
+
+TPM_RH_LOCKOUT
+Auth Index: 1
+Auth Role: USER
+
+UINT32
+
+newMaxTries
+
+count of authorization failures before the lockout is
+imposed
+
+UINT32
+
+newRecoveryTime
+
+time in seconds before the authorization failure count
+is automatically decremented
+A value of zero indicates that DA protection is
+disabled.
+
+UINT32
+
+lockoutRecovery
+
+time in seconds after a lockoutAuth failure before use
+of lockoutAuth is allowed
+A value of zero indicates that a reboot is required.
+
+Table 168 — TPM2_DictionaryAttackParameters Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 335
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+27.3.3 Detailed Actions
+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
+33
+
+#include "InternalRoutines.h"
+#include "DictionaryAttackParameters_fp.h"
+
+TPM_RC
+TPM2_DictionaryAttackParameters(
+DictionaryAttackParameters_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+// Set dictionary attack parameters
+gp.maxTries = in->newMaxTries;
+gp.recoveryTime = in->newRecoveryTime;
+gp.lockoutRecovery = in->lockoutRecovery;
+// Set failed tries to 0
+gp.failedTries = 0;
+// Record the changes to NV
+NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
+NvWriteReserved(NV_MAX_TRIES, &gp.maxTries);
+NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime);
+NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery);
+return TPM_RC_SUCCESS;
+}
+
+Page 336
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+28
+
+Part 3: Commands
+
+Miscellaneous Management Functions
+
+28.1
+
+Introduction
+
+This clause contains commands that do not logically group with any other commands.
+28.2
+
+TPM2_PP_Commands
+
+28.2.1 General Description
+This command is used to determine which commands require assertion of Physical Presence (PP) in
+addition to platformAuth/platformPolicy.
+This command requires that auth is TPM_RH_PLATFORM and that Physical Presence be asserted.
+After this command executes successfully, the commands listed in setList will be added to the list of
+commands that require that Physical Presence be asserted when the handle associated with the
+authorization is TPM_RH_PLATFORM. The commands in clearList will no longer require assertion of
+Physical Presence in order to authorize a command.
+If a command is not in either list, its state is not changed. If a command is in both lists, then it will no
+longer require Physical Presence (for example, setList is processed first).
+Only commands with
+handle types of
+TPMI_RH_PLATFORM, TPMI_RH_PROVISION,
+TPMI_RH_CLEAR, or TPMI_RH_HIERARCHY can be gated with Physical Presence. If any other
+command is in either list, it is discarded.
+When a command requires that Physical Presence be provided, then Physical Presence shall be
+asserted for either an HMAC or a Policy authorization.
+NOTE
+
+Physical Presence may be made a requirement of any policy.
+
+TPM2_PP_Commands() always requires assertion of Physical Presence.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 337
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+28.2.2 Command and Response
+Table 169 — TPM2_PP_Commands Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_PP_Commands {NV}
+
+TPMI_RH_PLATFORM
+
+@auth
+
+TPM_RH_PLATFORM+PP
+Auth Index: 1
+Auth Role: USER + Physical Presence
+
+TPML_CC
+
+setList
+
+list of commands to be added to those that will require
+that Physical Presence be asserted
+
+TPML_CC
+
+clearList
+
+list of commands that will no longer require that
+Physical Presence be asserted
+
+Table 170 — TPM2_PP_Commands Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 338
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+28.2.3 Detailed Actions
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+
+#include "InternalRoutines.h"
+#include "PP_Commands_fp.h"
+
+TPM_RC
+TPM2_PP_Commands(
+PP_Commands_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+UINT32
+TPM_RC
+
+i;
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+// Process set list
+for(i = 0; i < in->setList.count; i++)
+// If command is implemented, set it as PP required. If the input
+// command is not a PP command, it will be ignored at
+// PhysicalPresenceCommandSet().
+if(CommandIsImplemented(in->setList.commandCodes[i]))
+PhysicalPresenceCommandSet(in->setList.commandCodes[i]);
+// Process clear list
+for(i = 0; i < in->clearList.count; i++)
+// If command is implemented, clear it as PP required. If the input
+// command is not a PP command, it will be ignored at
+// PhysicalPresenceCommandClear(). If the input command is
+// TPM2_PP_Commands, it will be ignored as well
+if(CommandIsImplemented(in->clearList.commandCodes[i]))
+PhysicalPresenceCommandClear(in->clearList.commandCodes[i]);
+// Save the change of PP list
+NvWriteReserved(NV_PP_LIST, &gp.ppList);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 339
+October 31, 2013
+
+ Part 3: Commands
+
+28.3
+
+Trusted Platform Module Library
+
+TPM2_SetAlgorithmSet
+
+28.3.1 General Description
+This command allows the platform to change the set of algorithms that are used by the TPM. The
+algorithmSet setting is a vendor-dependent value.
+If the changing of the algorithm set results in a change of the algorithms of PCR banks, then the TPM will
+need to be reset (_TPM_Init and TPM2_Startup(TPM_SU_CLEAR)) before the new PCR settings take
+effect. After this command executes successfully, if startupType in the next TPM2_Startup() is not
+TPM_SU_CLEAR, the TPM shall return TPM_RC_VALUE and enter Failure mode.
+This command does not change the algorithms available to the platform.
+NOTE
+
+The reference implementation does not have support for this command. In particular, it does not
+support use of this command to selectively disable algorithms. Proper support wo uld require
+modification of the unmarshaling code so that each time an algorithm is unmarshaled, it would be
+verified as being enabled.
+
+Page 340
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+28.3.2 Command and Response
+Table 171 — TPM2_SetAlgorithmSet Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_SetAlgorithmSet {NV}
+
+TPMI_RH_PLATFORM
+
+@authHandle
+
+TPM_RH_PLATFORM
+Auth Index: 1
+Auth Role: USER
+
+UINT32
+
+algorithmSet
+
+a TPM vendor-dependent value indicating the
+algorithm set selection
+
+Table 172 — TPM2_SetAlgorithmSet Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 341
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+28.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
+#include "InternalRoutines.h"
+#include "SetAlgorithmSet_fp.h"
+
+TPM_RC
+TPM2_SetAlgorithmSet(
+SetAlgorithmSet_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Internal Data Update
+gp.algorithmSet = in->algorithmSet;
+// Write the algorithm set changes to NV
+NvWriteReserved(NV_ALGORITHM_SET, &gp.algorithmSet);
+return TPM_RC_SUCCESS;
+}
+
+Page 342
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+Field Upgrade
+
+29
+29.1
+
+Introduction
+
+This clause contains the commands for managing field upgrade of the firmware in the TPM. The field
+upgrade scheme may be used for replacement or augmentation of the firmware installed in the TPM.
+EXAMPLE 1
+
+If an algorithm is found to be flawed, a patch of that algorithm might be installed using the firmware
+upgrade process. The patch might be a replacement of a portion of the code or a complete
+replacement of the firmware.
+
+EXAMPLE 2
+
+If an additional set of ECC parameters is needed, the firmware process may be used to add the
+parameters to the TPM data set.
+
+The
+field
+upgrade
+process
+uses
+two
+commands
+(TPM2_FieldUpgradeStart()
+and
+TPM2_FieldUpgradeData()). TPM2_FieldUpgradeStart() validates that a signature on the provided digest
+is from the TPM manufacturer and that proper authorization is provided using platformPolicy.
+NOTE 1
+
+The platformPolicy for field upgraded is defined by the PM and may include requirements that the
+upgrade be signed by the PM or the TPM owner and include any other constraints that are desired
+by the PM.
+
+If the proper authorization is given, the TPM will retain the signed digest and enter the Field Upgrade
+mode (FUM). While in FUM, the TPM will accept TPM2_FieldUpgradeData() commands. It may accept
+other commands if it is able to complete them using the previously installed firmware. Otherwise, it will
+return TPM_RC_UPGRADE.
+Each block of the field upgrade shall contain the digest of the next block of the field upgrade data. That
+digest shall be included in the digest of the previous block. The digest of the first block is signed by the
+TPM manufacturer. That signature and first block digest are the parameters for
+TPM2_FieldUpgradeStart(). The digest is saved in the TPM as the required digest for the next field
+upgrade data block and as the identifier of the field upgrade sequence.
+For each field upgrade data block that is sent to the TPM by TPM2_FieldUpgradeData(), the TPM shall
+validate that the digest matches the required digest and if not, shall return TPM_RC_VALUE. The TPM
+shall extract the digest of the next expected block and return that value to the caller, along with the digest
+of the first data block of the update sequence.
+The system may attempt to abandon the firmware upgrade by using a zero-length buffer in
+TPM2_FieldUpdateData(). If the TPM is able to resume operation using the firmware present when the
+upgrade started, then the TPM will indicate that it has abandon the update by setting the digest of the
+next block to the Empty Buffer. If the TPM cannot abandon the update, it will return the expected next
+digest.
+The system may also attempt to abandon the update because of a power interruption. If the TPM is able
+to resume normal operations, then it will respond normally to TPM2_Startup(). If the TPM is not able to
+resume normal operations, then it will respond to any command but TPM2_FieldUpgradeData() with
+TPM_RC_FIELDUPGRADE.
+After a _TPM_Init, system software may not be able to resume the field upgrade that was in process
+when the power interruption occurred. In such case, the TPM firmware may be reset to one of two other
+values:
+
+
+the original firmware that was installed at the factory (“initial firmware”); or
+
+
+
+the firmware that was in the TPM when the field upgrade process started (“previous firmware”).
+
+The TPM retains the digest of the first block for these firmware images and checks to see if the first block
+after _TPM_Init matches either of those digests. If so, the firmware update process restarts and the
+original firmware may be loaded.
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 343
+October 31, 2013
+
+ Part 3: Commands
+NOTE 2
+
+Trusted Platform Module Library
+
+The TPM is required to accept the previous firmware as either a vendor -provided update or as
+recovered from the TPM using TPM2_FirmwareRead().
+
+When the last block of the firmware upgrade is loaded into the TPM (indicated to the TPM by data in the
+data block in a TPM vendor-specific manner), the TPM will complete the upgrade process. If the TPM is
+able to resume normal operations without a reboot, it will set the hash algorithm of the next block to
+TPM_ALG_NULL and return TPM_RC_SUCCESS. If a reboot is required, the TPM shall return
+TPM_RC_REBOOT in response to the last TPM2_FieldUpgradeData() and all subsequent TPM
+commands until a _TPM_Init is received.
+NOTE 3
+
+Because no additional data is allowed when the res ponse code is not TPM_RC_SUCCESS, the TPM
+returns TPM_RC_SUCCESS for all calls to TPM2_FieldUpgradeData() except the last. In this
+manner, the TPM is able to indicate the digest of the next block. If a _TPM_Init occurs while the
+TPM is in FUM, the next block may be the digest for the first block of the original firmware. If it is
+not, then the TPM will not accept the original firmware until the next _TPM_Init when the TPM is in
+FUM.
+
+During the field upgrade process, the TPM shall preserve:
+
+
+Primary Seeds;
+
+
+
+Hierarchy authValue, authPolicy, and proof values;
+
+
+
+Lockout authValue and authorization failure count values;
+
+
+
+PCR authValue and authPolicy values;
+
+
+
+NV Index allocations and contents;
+
+
+
+Persistent object allocations and contents; and
+
+
+
+Clock.
+
+Page 344
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+29.2
+
+Part 3: Commands
+
+TPM2_FieldUpgradeStart
+
+29.2.1 General Description
+This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a Field Upgrade
+Manifest.
+If the signature checks
+TPM2_FieldUpgradeData().
+
+succeed,
+
+the
+
+authorization
+
+is
+
+valid
+
+and
+
+the
+
+TPM
+
+will
+
+accept
+
+This signature is checked against the loaded key referenced by keyHandle. This key will have a Name
+that is the same as a value that is part of the TPM firmware data. If the signature is not valid, the TPM
+shall return TPM_RC_SIGNATURE.
+NOTE
+
+A loaded key is used rather than a hard-coded key to reduce the amount of memory needed for this
+key data in case more than one vendor key is needed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 345
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+29.2.2 Command and Response
+Table 173 — TPM2_FieldUpgradeStart Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_FieldUpgradeStart
+
+TPMI_RH_PLATFORM
+
+@authorization
+
+TPM_RH_PLATFORM+{PP}
+Auth Index:1
+Auth Role: ADMIN
+
+TPMI_DH_OBJECT
+
+keyHandle
+
+handle of a public area that contains the TPM Vendor
+Authorization Key that will be used to validate
+manifestSignature
+Auth Index: None
+
+TPM2B_DIGEST
+
+fuDigest
+
+digest of the first block in the field upgrade sequence
+
+TPMT_SIGNATURE
+
+manifestSignature
+
+signature over fuDigest using the key associated with
+keyHandle (not optional)
+
+Table 174 — TPM2_FieldUpgradeStart Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 346
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+29.2.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+#include "InternalRoutines.h"
+#include "FieldUpgradeStart_fp.h"
+#if CC_FieldUpgradeStart == YES
+
+TPM_RC
+TPM2_FieldUpgradeStart(
+FieldUpgradeStart_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+// Not implemented
+UNUSED_PARAMETER(in);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 347
+October 31, 2013
+
+ Part 3: Commands
+
+29.3
+
+Trusted Platform Module Library
+
+TPM2_FieldUpgradeData
+
+29.3.1 General Description
+This command will take the actual field upgrade image to be installed on the TPM. The exact format of
+fuData is vendor-specific. This command is only possible following a successful
+TPM2_FieldUpgradeStart().
+If
+the
+TPM
+has
+not
+received
+a
+properly
+authorized
+TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE.
+The TPM will validate that the digest of fuData matches an expected value. If so, the TPM may buffer or
+immediately apply the update. If the digest of fuData does not match an expected value, the TPM shall
+return TPM_RC_VALUE.
+
+Page 348
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+29.3.2 Command and Response
+Table 175 — TPM2_FieldUpgradeData Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_FieldUpgradeData {NV}
+
+TPM2B_MAX_BUFFER
+
+fuData
+
+field upgrade image data
+
+Table 176 — TPM2_FieldUpgradeData Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMT_HA+
+
+nextDigest
+
+tagged digest of the next block
+TPM_ALG_NULL if field update is complete
+
+TPMT_HA
+
+firstDigest
+
+tagged digest of the first block of the sequence
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 349
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+29.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+
+#include "InternalRoutines.h"
+#include "FieldUpgradeData_fp.h"
+#if CC_FieldUpgradeData == YES
+
+TPM_RC
+TPM2_FieldUpgradeData(
+FieldUpgradeData_In
+FieldUpgradeData_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Not implemented
+UNUSED_PARAMETER(in);
+UNUSED_PARAMETER(out);
+return TPM_RC_SUCCESS;
+}
+#endif
+
+Page 350
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+29.4
+
+Part 3: Commands
+
+TPM2_FirmwareRead
+
+29.4.1 General Description
+This command is used to read a copy of the current firmware installed in the TPM.
+The presumption is that the data will be returned in reverse order so that the last block in the sequence
+would be the first block given to the TPM in case of a failure recovery. If the TPM2_FirmwareRead
+sequence completes successfully, then the data provided from the TPM will be sufficient to allow the TPM
+to recover from an abandoned upgrade of this firmware.
+To start the sequence of retrieving the data, the caller sets sequenceNumber to zero. When the TPM has
+returned all the firmware data, the TPM will return the Empty Buffer as fuData.
+The contents of fuData are opaque to the caller.
+NOTE 1
+
+The caller should retain the ordering of the update blocks so that the blocks sent to the TPM have
+the same size and inverse order as the blocks returned by a sequence of calls to this command.
+
+NOTE 2
+
+Support for this command is optional even if the TPM implements TPM2_FieldUpgradeStart() and
+TPM2_FieldUpgradeData().
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 351
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+29.4.2 Command and Response
+Table 177 — TPM2_FirmwareRead Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_FirmwareRead
+
+UINT32
+
+sequenceNumber
+
+the number of previous calls to this command in this
+sequence
+set to 0 on the first call
+
+Table 178 — TPM2_FirmwareRead Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_BUFFER
+
+fuData
+
+Page 352
+October 31, 2013
+
+field upgrade image data
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+29.4.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+
+#include "InternalRoutines.h"
+#include "FirmwareRead_fp.h"
+
+TPM_RC
+TPM2_FirmwareRead(
+FirmwareRead_In
+FirmwareRead_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Not implemented
+UNUSED_PARAMETER(in);
+UNUSED_PARAMETER(out);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 353
+October 31, 2013
+
+ Part 3: Commands
+
+30
+
+Trusted Platform Module Library
+
+Context Management
+
+30.1
+
+Introduction
+
+Three of the commands in this clause (TPM2_ContextSave(), TPM2_ContextLoad(), and
+TPM2_FlushContext()) implement the resource management described in the "Context Management"
+clause in Part 1.
+The fourth command in this clause (TPM2_EvictControl()) is used to control the persistence of a loadable
+objects in TPM memory. Background for this command may be found in the "Owner and Platform Evict
+Objects" clause in Part 1.
+30.2
+
+TPM2_ContextSave
+
+30.2.1 General Description
+This command saves a session context, object context, or sequence object context outside the TPM.
+No authorization sessions of any type are allowed with this command and tag is required to be
+TPM_ST_NO_SESSIONS.
+NOTE
+
+This preclusion avoids complex issues of dealing with the same session in handle and in the session
+area. While it might be possible to provide specificity, it would add unnecessary complexity to the
+TPM and, because this capability would provide no application benefit, use of authorization ses sions
+for audit or encryption is prohibited.
+
+The TPM shall encrypt and integrity protect the context as described in the "Context Protection" clause in
+Part 1.
+See the “Context Data” clause in Part 2 for a description of the context structure in the response.
+
+Page 354
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.2.2 Command and Response
+Table 179 — TPM2_ContextSave Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ContextSave
+
+TPMI_DH_CONTEXT
+
+saveHandle
+
+handle of the resource to save
+Auth Index: None
+
+Table 180 — TPM2_ContextSave Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMS_CONTEXT
+
+context
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 355
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.2.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ContextSave_fp.h"
+#include "Context_spt_fp.h"
+Error Returns
+TPM_RC_CONTEXT_GAP
+
+a contextID could not be assigned for a session context save
+
+TPM_RC_TOO_MANY_CONTEXTS
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+
+Meaning
+
+no more contexts can be saved as the counter has maxed out
+
+TPM_RC
+TPM2_ContextSave(
+ContextSave_In
+ContextSave_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+UINT16
+// blob.
+UINT64
+TPM2B_SYM_KEY
+TPM2B_IV
+
+result;
+fingerprintSize;
+
+TPM2B_DIGEST
+UINT16
+BYTE
+
+integrity;
+integritySize;
+*buffer;
+
+contextID = 0;
+symKey;
+iv;
+
+// The size of fingerprint in context
+// session context ID
+
+// This command may cause the orderlyState to be cleared due to
+// the update of state reset data. If this is the case, check if NV is
+// available first
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+}
+// Internal Data Update
+// Initialize output handle. At the end of command action, the output
+// handle of an object will be replaced, while the output handle
+// for a session will be the same as input
+out->context.savedHandle = in->saveHandle;
+// Get the size of fingerprint in context blob. The sequence value in
+// TPMS_CONTEXT structure is used as the fingerprint
+fingerprintSize = sizeof(out->context.sequence);
+// Compute the integrity size at the beginning of context blob
+integritySize = sizeof(integrity.t.size)
++ CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
+// Perform object or session specific context save
+switch(HandleGetType(in->saveHandle))
+{
+case TPM_HT_TRANSIENT:
+{
+
+Page 356
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+
+OBJECT
+OBJECT
+
+Part 3: Commands
+
+*object = ObjectGet(in->saveHandle);
+*outObject =
+(OBJECT *)(out->context.contextBlob.t.buffer
++ integritySize + fingerprintSize);
+
+// Set size of the context data. The contents of context blob is vendor
+// defined. In this implementation, the size is size of integrity
+// plus fingerprint plus the whole internal OBJECT structure
+out->context.contextBlob.t.size = integritySize +
+fingerprintSize + sizeof(*object);
+// Copy the whole internal OBJECT structure to context blob, leave
+// the size for fingerprint
+*outObject = *object;
+// Increment object context ID
+gr.objectContextID++;
+// If object context ID overflows, TPM should be put in failure mode
+if(gr.objectContextID == 0)
+FAIL(FATAL_ERROR_INTERNAL);
+// Fill in other return values for an object.
+out->context.sequence = gr.objectContextID;
+// For regular object, savedHandle is 0x80000000. For sequence object,
+// savedHandle is 0x80000001. For object with stClear, savedHandle
+// is 0x80000002
+if(ObjectIsSequence(object))
+{
+out->context.savedHandle = 0x80000001;
+SequenceDataImportExport(object, outObject, EXPORT_STATE);
+}
+else if(object->attributes.stClear == SET)
+{
+out->context.savedHandle = 0x80000002;
+}
+else
+{
+out->context.savedHandle = 0x80000000;
+}
+// Get object hierarchy
+out->context.hierarchy = ObjectDataGetHierarchy(object);
+break;
+}
+case TPM_HT_HMAC_SESSION:
+case TPM_HT_POLICY_SESSION:
+{
+SESSION
+*session = SessionGet(in->saveHandle);
+// Set size of the context data. The contents of context blob is vendor
+// defined. In this implementation, the size of context blob is the
+// size of a internal session structure plus the size of
+// fingerprint plus the size of integrity
+out->context.contextBlob.t.size = integritySize +
+fingerprintSize + sizeof(*session);
+// Copy the whole internal SESSION structure to context blob.
+// Save space for fingerprint at the beginning of the buffer
+// This is done before anything else so that the actual context
+// can be reclaimed after this call
+MemoryCopy(out->context.contextBlob.t.buffer
++ integritySize + fingerprintSize,
+session, sizeof(*session),
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 357
+October 31, 2013
+
+ Part 3: Commands
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+
+Trusted Platform Module Library
+sizeof(out->context.contextBlob.t.buffer)
+- integritySize - fingerprintSize);
+
+// Fill in the other return parameters for a session
+// Get a context ID and set the session tracking values appropriately
+// TPM_RC_CONTEXT_GAP is a possible error.
+// SessionContextSave() will flush the in-memory context
+// so no additional errors may occur after this call.
+result = SessionContextSave(out->context.savedHandle, &contextID);
+if(result != TPM_RC_SUCCESS) return result;
+// sequence number is the current session contextID
+out->context.sequence = contextID;
+// use TPM_RH_NULL as hierarchy for session context
+out->context.hierarchy = TPM_RH_NULL;
+break;
+}
+default:
+// SaveContext may only take an object handle or a session handle.
+// All the other handle type should be filtered out at unmarshal
+pAssert(FALSE);
+break;
+}
+// Save fingerprint at the beginning of encrypted area of context blob.
+// Reserve the integrity space
+MemoryCopy(out->context.contextBlob.t.buffer + integritySize,
+&out->context.sequence, sizeof(out->context.sequence),
+sizeof(out->context.contextBlob.t.buffer) - integritySize);
+// Compute context encryption key
+ComputeContextProtectionKey(&out->context, &symKey, &iv);
+// Encrypt context blob
+CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize,
+CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
+TPM_ALG_CFB, symKey.t.buffer, &iv,
+out->context.contextBlob.t.size - integritySize,
+out->context.contextBlob.t.buffer + integritySize);
+// Compute integrity hash for the object
+// In this implementation, the same routine is used for both sessions
+// and objects.
+ComputeContextIntegrity(&out->context, &integrity);
+// add integrity at the beginning of context blob
+buffer = out->context.contextBlob.t.buffer;
+TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
+// orderly state should be cleared because of the update of state reset and
+// state clear data
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 358
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+30.3
+
+Part 3: Commands
+
+TPM2_ContextLoad
+
+30.3.1 General Description
+This command is used to reload a context that has been saved by TPM2_ContextSave().
+No authorization sessions of any type are allowed with this command and tag is required to be
+TPM_ST_NO_SESSIONS (see note in 30.2.1).
+The TPM will return TPM_RC_HIERARCHY if the context is associated with a hierarchy that is disabled.
+NOTE
+
+Contexts for authorization sessions and for sequence object s belong to the NULL hierarchy which is
+never disabled.
+
+See the “Context Data” clause in Part 2 for a description of the values in the context parameter.
+If the integrity HMAC of the saved context is not valid, the TPM shall return TPM_RC_INTEGRITY.
+The TPM shall perform a check on the decrypted context as described in the "Context Confidentiality
+Protections" clause of Part 1 and enter failure mode if the check fails.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 359
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.3.2 Command and Response
+Table 181 — TPM2_ContextLoad Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ContextLoad
+
+TPMS_CONTEXT
+
+context
+
+the context blob
+
+Table 182 — TPM2_ContextLoad Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_DH_CONTEXT
+
+loadedHandle
+
+Page 360
+October 31, 2013
+
+the handle assigned to the resource after it has been
+successfully loaded
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.3.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "ContextLoad_fp.h"
+#include "Context_spt_fp.h"
+Error Returns
+TPM_RC_CONTEXT_GAP
+
+there is only one available slot and this is not the oldest saved
+session context
+
+TPM_RC_HANDLE
+
+'context. savedHandle' does not reference a saved session
+
+TPM_RC_HIERARCHY
+
+'context.hierarchy' is disabled
+
+TPM_RC_INTEGRITY
+
+context integrity check fail
+
+TPM_RC_OBJECT_MEMORY
+
+no free slot for an object
+
+TPM_RC_SESSION_MEMORY
+
+no free session slots
+
+TPM_RC_SIZE
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
+Meaning
+
+incorrect context blob size
+
+TPM_RC
+TPM2_ContextLoad(
+ContextLoad_In
+ContextLoad_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Local Variables
+TPM_RC
+result = TPM_RC_SUCCESS;
+TPM2B_DIGEST
+TPM2B_DIGEST
+UINT16
+UINT64
+BYTE
+INT32
+
+ingerityToCompare;
+integrity;
+integritySize;
+fingerprint;
+*buffer;
+size;
+
+TPM_HT
+TPM2B_SYM_KEY
+TPM2B_IV
+
+handleType;
+symKey;
+iv;
+
+// Input Validation
+// Check context blob size
+handleType = HandleGetType(in->context.savedHandle);
+// Check integrity
+// In this implementation, the same routine is used for both sessions
+// and objects.
+integritySize = sizeof(integrity.t.size)
++ CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
+// Get integrity from context blob
+buffer = in->context.contextBlob.t.buffer;
+size = (INT32) in->context.contextBlob.t.size;
+result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Compute context integrity
+ComputeContextIntegrity(&in->context, &ingerityToCompare);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 361
+October 31, 2013
+
+ Part 3: Commands
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+
+Trusted Platform Module Library
+
+// Compare integrity
+if(!Memory2BEqual(&integrity.b, &ingerityToCompare.b))
+return TPM_RC_INTEGRITY + RC_ContextLoad_context;
+// Compute context encryption key
+ComputeContextProtectionKey(&in->context, &symKey, &iv);
+// Decrypt context data in place
+CryptSymmetricDecrypt(in->context.contextBlob.t.buffer + integritySize,
+CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
+TPM_ALG_CFB, symKey.t.buffer, &iv,
+in->context.contextBlob.t.size - integritySize,
+in->context.contextBlob.t.buffer + integritySize);
+// Read the fingerprint value, skip the leading integrity size
+MemoryCopy(&fingerprint, in->context.contextBlob.t.buffer + integritySize,
+sizeof(fingerprint), sizeof(fingerprint));
+// Check fingerprint. If the check fails, TPM should be put to failure mode
+if(fingerprint != in->context.sequence)
+FAIL(FATAL_ERROR_INTERNAL);
+// Perform object or session specific input check
+switch(handleType)
+{
+case TPM_HT_TRANSIENT:
+{
+// Get a pointer to the object in the context blob
+OBJECT
+*outObject = (OBJECT *)(in->context.contextBlob.t.buffer
++ integritySize + sizeof(fingerprint));
+// Discard any changes to the handle that the TRM might have made
+in->context.savedHandle = TRANSIENT_FIRST;
+// If hierarchy is disabled, no object context can be loaded in this
+// hierarchy
+if(!HierarchyIsEnabled(in->context.hierarchy))
+return TPM_RC_HIERARCHY + RC_ContextLoad_context;
+// Restore object. A TPM_RC_OBJECT_MEMORY error may be returned at
+// this point
+result = ObjectContextLoad(outObject, &out->loadedHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+// If this is a sequence object, the crypto library may need to
+// reformat the data into an internal format
+if(ObjectIsSequence(outObject))
+SequenceDataImportExport(ObjectGet(out->loadedHandle),
+outObject, IMPORT_STATE);
+break;
+}
+case TPM_HT_POLICY_SESSION:
+case TPM_HT_HMAC_SESSION:
+{
+SESSION
+
+*session = (SESSION *)(in->context.contextBlob.t.buffer
++ integritySize + sizeof(fingerprint));
+
+// This command may cause the orderlyState to be cleared due to
+// the update of state reset data. If this is the case, check if NV is
+// available first
+
+Page 362
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+
+Part 3: Commands
+
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned
+// at this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Check if input handle points to a valid saved session
+if(!SessionIsSaved(in->context.savedHandle))
+return TPM_RC_HANDLE + RC_ContextLoad_context;
+// Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
+// may be returned at this point
+result = SessionContextLoad(session, &in->context.savedHandle);
+if(result != TPM_RC_SUCCESS)
+return result;
+out->loadedHandle = in->context.savedHandle;
+// orderly state should be cleared because of the update of state
+// reset and state clear data
+g_clearOrderly = TRUE;
+break;
+}
+default:
+// Context blob may only have an object handle or a session handle.
+// All the other handle type should be filtered out at unmarshal
+pAssert(FALSE);
+break;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 363
+October 31, 2013
+
+ Part 3: Commands
+
+30.4
+
+Trusted Platform Module Library
+
+TPM2_FlushContext
+
+30.4.1 General Description
+This command causes all context associated with a loaded object or session to be removed from TPM
+memory.
+This command may not be used to remove a persistent object from the TPM.
+A session does not have to be loaded in TPM memory to have its context flushed. The saved session
+context associated with the indicated handle is invalidated.
+No sessions of any type are allowed with
+TPM_ST_NO_SESSIONS (see note in 30.2.1).
+
+this
+
+command
+
+and
+
+tag
+
+is
+
+required
+
+to
+
+be
+
+If the handle is for a transient object and the handle is not associated with a loaded object, then the TPM
+shall return TPM_RC_HANDLE.
+If the handle is for an authorization session and the handle does not reference a loaded or active session,
+then the TPM shall return TPM_RC_HANDLE.
+NOTE
+
+flushHandle is a parameter and not a handle. If it were in the handle area, the TPM would validate
+that the context for the referenced entity is in the TPM. When a TPM2_FlushContext references a
+saved session context, it is not necessary for the context to be in the TPM .
+
+Page 364
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.4.2 Command and Response
+Table 183 — TPM2_FlushContext Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPMI_DH_CONTEXT
+
+flushHandle
+
+TPM_CC_FlushContext
+the handle of the item to flush
+NOTE
+
+This is a use of a handle as a parameter.
+
+Table 184 — TPM2_FlushContext Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 365
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "FlushContext_fp.h"
+Error Returns
+TPM_RC_HANDLE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
+Meaning
+flushHandle does not reference a loaded object or session
+
+TPM_RC
+TPM2_FlushContext(
+FlushContext_In
+)
+{
+// Internal Data Update
+
+*in
+
+// IN: input parameter list
+
+// Call object or session specific routine to flush
+switch(HandleGetType(in->flushHandle))
+{
+case TPM_HT_TRANSIENT:
+if(!ObjectIsPresent(in->flushHandle))
+return TPM_RC_HANDLE;
+// Flush object
+ObjectFlush(in->flushHandle);
+break;
+case TPM_HT_HMAC_SESSION:
+case TPM_HT_POLICY_SESSION:
+if(
+!SessionIsLoaded(in->flushHandle)
+&& !SessionIsSaved(in->flushHandle)
+)
+return TPM_RC_HANDLE;
+// If the session to be flushed is the exclusive audit session, then
+// indicate that there is no exclusive audit session any longer.
+if(in->flushHandle == g_exclusiveAuditSession)
+g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
+// Flush session
+SessionFlush(in->flushHandle);
+break;
+default:
+// This command only take object or session handle.
+// should be filtered out at handle unmarshal
+pAssert(FALSE);
+break;
+}
+
+Other handles
+
+return TPM_RC_SUCCESS;
+}
+
+Page 366
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+30.5
+
+Part 3: Commands
+
+TPM2_EvictControl
+
+30.5.1 General Description
+This command allows a transient object to be made persistent or a persistent object to be evicted.
+NOTE 1
+
+A transient object is one that may be removed from TPM memory using either TPM2_FlushContext
+or TPM2_Startup(). A persistent object is not removed from TPM memory by TPM2_FlushContext()
+or TPM2_Startup().
+
+If objectHandle is a transient object, then the call is to make the object persistent and assign
+persistentHandle to the persistent version of the object. If objectHandle is a persistent object, then the call
+is to evict the persistent object.
+Before execution of TPM2_EvictControl code below, the TPM verifies that objectHandle references an
+object that is resident on the TPM and that persistentHandle is a valid handle for a persistent object.
+NOTE 2
+
+This requirement simplifies the unmarshaling code so that it only need check that persistentHandle
+is always a persistent object.
+
+If objectHandle references a transient object:
+a) The TPM shall return TPM_RC_ATTRIBUTES if
+1) it is in the hierarchy of TPM_RH_NULL,
+2) only the public portion of the object is loaded, or
+3) the stClear is SET in the object or in an ancestor key.
+b) The TPM shall return TPM_RC_HIERARCHY if the object is not in the proper hierarchy as
+determined by auth.
+1) If auth is TPM_RH_PLATFORM, the proper hierarchy is the Platform hierarchy.
+2) If auth is TPM_RH_OWNER, the proper hierarchy is either the Storage or the Endorsement
+hierarchy.
+c) The TPM shall return TPM_RC_RANGE if persistentHandle is not in the proper range as determined
+by auth.
+1) If auth is TPM_RH_OWNER, then persistentHandle shall be in the inclusive range of
+81 00 00 0016 to 81 7F FF FF16.
+2) If auth is TPM_RH_PLATFORM, then persistentHandle shall be in the inclusive range of
+81 80 00 0016 to 81 FF FF FF16.
+d) The TPM shall return TPM_RC_NV_DEFINED if a persistent object exists with the same handle as
+persistentHandle.
+e) The TPM shall return TPM_RC_NV_SPACE if insufficient space is available to make the object
+persistent.
+f)
+
+The TPM shall return TPM_RC_NV_SPACE if execution of this command will prevent the TPM from
+being able to hold two transient objects of any kind.
+NOTE 3
+
+This requirement anticipates that a TPM may be implemented such that all TPM memory is non volatile and not subject to endurance issues. In such case, there is no movement of an object
+between memory of different types and it is necessary that the TPM ensure that it is always
+possible for the management software to move objects to/from TPM memory in order to ensure
+that the objects required for command execution can be context restored.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 367
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+g) If the TPM returns TPM_RC_SUCCESS, the object referenced by objectHandle will not be flushed
+and both objectHandle and persistentHandle may be used to access the object.
+If objectHandle references a persistent object:
+h) The TPM shall return TPM_RC_RANGE if objectHandle is not in the proper range as determined by
+auth. If auth is TPM_RC_OWNER, objectHandle shall be in the inclusive range of 81 00 00 0016 to
+81 7F FF FF16. If auth is TPM_RC_PLATFORM, objectHandle may be any valid persistent object
+handle.
+i)
+
+If the TPM returns TPM_RC_SUCCESS, objectHandle will be removed from persistent memory and
+no longer be accessible.
+
+NOTE 4
+
+The persistent object is not converted to a transient object, as this would prevent the immediate
+revocation of an object by removing it from persistent memory.
+
+Page 368
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+30.5.2 Command and Response
+Table 185 — TPM2_EvictControl Command
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_EvictControl {NV}
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPMI_DH_OBJECT
+
+objectHandle
+
+the handle of a loaded object
+Auth Index: None
+
+TPMI_DH_PERSISTENT
+
+persistentHandle
+
+if objectHandle is a transient object handle, then this is
+the persistent handle for the object
+if objectHandle is a persistent object handle, then this
+shall be the same value as persistentHandle
+
+Description
+
+Table 186 — TPM2_EvictControl Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 369
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+30.5.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "EvictControl_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+an object with temporary, stClear or publicOnly attribute SET cannot
+be made persistent
+
+TPM_RC_HIERARCHY
+
+auth cannot authorize the operation in the hierarchy of evictObject
+
+TPM_RC_HANDLE
+
+evictHandle of the persistent object to be evicted is not the same as
+the persistentHandle argument
+
+TPM_RC_NV_HANDLE
+
+persistentHandle is unavailable
+
+TPM_RC_NV_SPACE
+
+no space in NV to make evictHandle persistent
+
+TPM_RC_RANGE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+
+Meaning
+
+persistentHandle is not in the range corresponding to the hierarchy of
+evictObject
+
+TPM_RC
+TPM2_EvictControl(
+EvictControl_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+OBJECT
+
+result;
+*evictObject;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// Get internal object pointer
+evictObject = ObjectGet(in->objectHandle);
+// Temporary, stClear or public only objects can not be made persistent
+if(
+evictObject->attributes.temporary == SET
+|| evictObject->attributes.stClear == SET
+|| evictObject->attributes.publicOnly == SET
+)
+return TPM_RC_ATTRIBUTES + RC_EvictControl_objectHandle;
+// If objectHandle refers to a persistent object, it should be the same as
+// input persistentHandle
+if(
+evictObject->attributes.evict == SET
+&& evictObject->evictHandle != in->persistentHandle
+)
+return TPM_RC_HANDLE + RC_EvictControl_objectHandle;
+// Additional auth validation
+if(in->auth == TPM_RH_PLATFORM)
+{
+// To make persistent
+if(evictObject->attributes.evict == CLEAR)
+{
+// Platform auth can not set evict object in storage or endorsement
+// hierarchy
+
+Page 370
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+
+Part 3: Commands
+
+if(evictObject->attributes.ppsHierarchy == CLEAR)
+return TPM_RC_HIERARCHY + RC_EvictControl_objectHandle;
+// Platform cannot use a handle outside of platform persistent range.
+if(!NvIsPlatformPersistentHandle(in->persistentHandle))
+return TPM_RC_RANGE + RC_EvictControl_persistentHandle;
+}
+// Platform auth can delete any persistent object
+}
+else if(in->auth == TPM_RH_OWNER)
+{
+// Owner auth can not set or clear evict object in platform hierarchy
+if(evictObject->attributes.ppsHierarchy == SET)
+return TPM_RC_HIERARCHY + RC_EvictControl_objectHandle;
+// Owner cannot use a handle outside of owner persistent range.
+if(
+evictObject->attributes.evict == CLEAR
+&& !NvIsOwnerPersistentHandle(in->persistentHandle)
+)
+return TPM_RC_RANGE + RC_EvictControl_persistentHandle;
+}
+else
+{
+// Other auth is not allowed in this command and should be filtered out
+// at unmarshal process
+pAssert(FALSE);
+}
+// Internal Data Update
+// Change evict state
+if(evictObject->attributes.evict == CLEAR)
+{
+// Make object persistent
+// A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this
+// point
+result = NvAddEvictObject(in->persistentHandle, evictObject);
+if(result != TPM_RC_SUCCESS) return result;
+}
+else
+{
+// Delete the persistent object in NV
+NvDeleteEntity(evictObject->evictHandle);
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 371
+October 31, 2013
+
+ Part 3: Commands
+
+31
+
+Trusted Platform Module Library
+
+Clocks and Timers
+
+31.1
+
+TPM2_ReadClock
+
+31.1.1 General Description
+This command reads the current TPMS_TIME_INFO structure that contains the current setting of Time,
+Clock, resetCount, and restartCount.
+No authorization sessions of any type are allowed with this command and tag is required to be
+TPM_ST_NO_SESSIONS.
+NOTE
+
+This command is intended to allow the TCB to have access to values that have the potential to be
+privacy sensitive. The values may be read without authorization because the TCB will not disclose
+these values. Since they are not signed and cannot be accessed in a command that uses an
+authorization session, it is not possible for any entity, other than the TCB, to be assured that the
+values are accurate.
+
+Page 372
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+31.1.2 Command and Response
+Table 187 — TPM2_ReadClock Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+TPM_ST_NO_SESSIONS
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ReadClock
+
+Table 188 — TPM2_ReadClock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+returnCode
+
+TPMS_TIME_INFO
+
+currentTime
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 373
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+31.1.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+#include "InternalRoutines.h"
+#include "ReadClock_fp.h"
+
+TPM_RC
+TPM2_ReadClock(
+ReadClock_Out *out
+)
+{
+// Command Output
+
+// OUT: output parameter list
+
+out->currentTime.time = g_time;
+TimeFillInfo(&out->currentTime.clockInfo);
+return TPM_RC_SUCCESS;
+}
+
+Page 374
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+31.2
+
+Part 3: Commands
+
+TPM2_ClockSet
+
+31.2.1 General Description
+This command is used to advance the value of the TPM’s Clock. The command will fail if newTime is less
+than the current value of Clock or if the new time is greater than FF FF 00 00 00 00 00 0016. If both of
+these checks succeed, Clock is set to newTime. If either of these checks fails, the TPM shall return
+TPM_RC_VALUE and make no change to Clock.
+NOTE
+
+This maximum setting would prevent Clock from rolling over to zero for approximately 8,000 years if
+the Clock update rate was set so that TPM time was passing 33 percent faster than real time. This
+would still be more than 6,000 years before Clock would roll over to zero. Because Clock will not roll
+over in the lifetime of the TPM, there is no need for external software to deal with the possibility that
+Clock may wrap around.
+
+If the value of Clock after the update makes the volatile and non-volatile versions of
+TPMS_CLOCK_INFO.clock differ by more than the reported update interval, then the TPM shall update
+the non-volatile version of TPMS_CLOCK_INFO.clock before returning.
+This command requires platformAuth or ownerAuth.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 375
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+31.2.2 Command and Response
+Table 189 — TPM2_ClockSet Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ClockSet {NV}
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+UINT64
+
+newTime
+
+new Clock setting in milliseconds
+
+Table 190 — TPM2_ClockSet Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+returnCode
+
+Page 376
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+31.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "ClockSet_fp.h"
+
+Read the current TPMS_TIMER_INFO structure settings
+Error Returns
+TPM_RC_VALUE
+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
+33
+34
+35
+
+Meaning
+invalid new clock
+
+TPM_RC
+TPM2_ClockSet(
+ClockSet_In *in
+)
+{
+#define CLOCK_UPDATE_MASK
+UINT64
+clockNow;
+
+// IN: input parameter list
+((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
+
+// Input Validation
+// new time can not be bigger than 0xFFFF000000000000 or smaller than
+// current clock
+if(in->newTime > 0xFFFF000000000000ULL
+|| in->newTime < go.clock)
+return TPM_RC_VALUE + RC_ClockSet_newTime;
+// Internal Data Update
+// Internal Data Update
+clockNow = go.clock;
+// grab the old value
+go.clock = in->newTime;
+// set the new value
+// Check to see if the update has caused a need for an nvClock update
+if((in->newTime & CLOCK_UPDATE_MASK) > (clockNow & CLOCK_UPDATE_MASK))
+{
+CryptDrbgGetPutState(GET_STATE);
+NvWriteReserved(NV_ORDERLY_DATA, &go);
+// Now the time state is safe
+go.clockSafe = YES;
+}
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 377
+October 31, 2013
+
+ Part 3: Commands
+
+31.3
+
+Trusted Platform Module Library
+
+TPM2_ClockRateAdjust
+
+31.3.1 General Description
+This command adjusts the rate of advance of Clock and Time to provide a better approximation to real
+time.
+The rateAdjust value is relative to the current rate and not the nominal rate of advance.
+EXAMPLE 1
+
+If this command had been called three times with rateAdjust = TPM_CLOCK_COARSE_SLOWER
+and once with rateAdjust = TPM_CLOCK_COARSE_FASTER, the net effect will be as if the
+command had been called twice with rateAdjust = TPM_CLOCK_COARSE_SLOWER.
+
+The range of adjustment shall be sufficient to allow Clock and Time to advance at real time but no more.
+If the requested adjustment would make the rate advance faster or slower than the nominal accuracy of
+the input frequency, the TPM shall return TPM_RC_VALUE.
+EXAMPLE 2
+
+If the frequency tolerance of the TPM's input clock is +/-10 percent, then the TPM will return
+TPM_RC_VALUE if the adjustment would make Clock run more than 10 percent faster or slower than
+nominal. That is, if the input oscillator were nominally 100 megahertz (MHz), then 1 millisecond (ms)
+would normally take 100,000 counts. The update Clock should be adjustable so that 1 ms is between
+90,000 and 110,000 counts.
+
+The interpretation of “fine” and “coarse” adjustments is implementation-specific.
+The nominal rate of advance for Clock and Time shall be accurate to within 15 percent. That is, with no
+adjustment applied, Clock and Time shall be advanced at a rate within 15 percent of actual time.
+NOTE
+
+If the adjustments are incorrect, it will be possible to m ake the difference between advance of
+Clock/Time and real time to be as much as 1.15 2 or ~1.33.
+
+Changes to the current Clock update rate adjustment need not be persisted across TPM power cycles.
+
+Page 378
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+31.3.2 Command and Response
+Table 191 — TPM2_ClockRateAdjust Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_ClockRateAdjust
+
+TPMI_RH_PROVISION
+
+@auth
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Handle: 1
+Auth Role: USER
+
+TPM_CLOCK_ADJUST
+
+rateAdjust
+
+Adjustment to current Clock update rate
+
+Table 192 — TPM2_ClockRateAdjust Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+returnCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 379
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+31.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+#include "InternalRoutines.h"
+#include "ClockRateAdjust_fp.h"
+
+TPM_RC
+TPM2_ClockRateAdjust(
+ClockRateAdjust_In
+*in
+)
+{
+// Internal Data Update
+TimeSetAdjustRate(in->rateAdjust);
+
+// IN: input parameter list
+
+return TPM_RC_SUCCESS;
+}
+
+Page 380
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+32
+
+Part 3: Commands
+
+Capability Commands
+
+32.1
+
+Introduction
+
+The TPM has numerous values that indicate the state, capabilities, and properties of the TPM. These
+values are needed for proper management of the TPM. The TPM2_GetCapability() command is used to
+access these values.
+TPM2_GetCapability() allows reporting of multiple values in a single call. The values are grouped
+according to type.
+NOTE
+
+32.2
+
+TPM2_TestParms()is used to determine if a TPM supports a particular combination of algorithm
+parameters
+
+TPM2_GetCapability
+
+32.2.1 General Description
+This command returns various information regarding the TPM and its current state.
+The capability parameter determines the category of data returned. The property parameter selects the
+first value of the selected category to be returned. If there is no property that corresponds to the value of
+property, the next higher value is returned, if it exists.
+EXAMPLE 1
+
+The list of handles of transient objects currently loaded in the TPM may be read one at a time. On
+the first read, set the property to TRANSIENT_FIRST and propertyCount to one. If a transient object
+is present, the lowest numbered handle is returned and moreData will be YES if transient objects
+with higher handles are loaded. On the subsequent call, use returned handle value plus 1 in order to
+access the next higher handle.
+
+The propertyCount parameter indicates the number of capabilities in the indicated group that are
+requested. The TPM will return the number of requested values (propertyCount) or until the last property
+of the requested type has been returned.
+NOTE 1
+
+The type of the capability is determined by a combination of capability and property.
+
+When all of the properties of the requested type have been returned, the moreData parameter in the
+response will be set to NO. Otherwise, it will be set to YES.
+NOTE 2
+
+The moreData parameter will be YES if there are more properties e ven if the requested number of
+capabilities has been returned.
+
+The TPM is not required to return more than one value at a time. It is not required to provide the same
+number of values in response to subsequent requests.
+EXAMPLE 2
+
+A TPM may return 4 properties in response to a TPM2_GetCapability(capability =
+TPM_CAP_TPM_PROPERTY, property = TPM_PT_MANUFACTURER, propertyCount = 8 ) and for a
+latter request with the same parameters, the TPM may return as few as one and as many as 8
+values.
+
+When the TPM is in Failure mode, a TPM is required to allow use of this command for access of the
+following capabilities:
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 381
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+
+
+TPM_PT_MANUFACTURER
+
+
+
+TPM_PT_VENDOR_STRING_1
+
+
+
+TPM_PT_VENDOR_STRING_2
+
+(3)
+
+
+
+TPM_PT_VENDOR_STRING_3
+
+(3)
+
+
+
+TPM_PT_VENDOR_STRING_4
+
+(3)
+
+
+
+TPM_PT_VENDOR_TPM_TYPE
+
+
+
+TPM_PT_FIRMWARE_VERSION_1
+
+
+
+TPM_PT_FIRMWARE_VERSION_2
+
+NOTE 3
+
+If the vendor string does not require one of these values, the property type does not need to exist.
+
+A vendor may optionally allow the TPM to return other values.
+If in Failure mode and a capability is requested that is not available in Failure mode, the TPM shall return
+no value.
+EXAMPLE 3
+
+Assume the TPM is in Failure mode and the TPM only supports reporting of the minimum required
+set of properties (the limited set to TPML_TAGGED_PCR_PROPERTY values). If a
+TPM2_GetCapability is received requesting a capability that has a property type value greater than
+TPM_PT_FIRMWARE_VERSION_2, the TPM will return a zero length list with the moreData
+parameter set to NO. If the property type is less than TPM_PT_M ANUFACTURER, the TPM will
+return TPM_PT_MANUFACTURER.
+
+In Failure mode, tag is required to be TPM_ST_NO_SESSIONS or the TPM shall return
+TPM_RC_FAILURE.
+The capability categories and the types of the return values are:
+capability
+
+Return Type
+
+property
+(1)
+
+TPM_CAP_ALGS
+
+TPM_ALG_ID
+
+TPML_ALG_PROPERTY
+
+TPM_CAP_HANDLES
+
+TPM_HANDLE
+
+TPML_HANDLE
+
+TPM_CAP_COMMANDS
+
+TPM_CC
+
+TPML_CCA
+
+TPM_CAP_PP_COMMANDS
+
+TPM_CC
+
+TPML_CC
+
+TPM_CAP_AUDIT_COMMANDS
+
+TPM_CC
+
+TPML_CC
+
+TPM_CAP_PCRS
+
+Reserved
+
+TPML_PCR_SELECTION
+
+TPM_CAP_TPM_PROPERTIES
+
+TPM_PT
+
+TPML_TAGGED_TPM_PROPERTY
+
+TPM_CAP_PCR_PROPERTIES
+
+TPM_PT_PCR
+
+TPML_TAGGED_PCR_PROPERTY
+(1)
+
+TPM_CAP_ECC_CURVE
+
+TPM_ECC_CURVE
+
+TPM_CAP_VENDOR_PROPERTY
+
+manufacturer specific
+
+TPML_ECC_CURVE
+manufacturer-specific values
+
+NOTES:
+(1) The TPM_ALG_ID or TPM_ECC_CURVE is cast to a UINT32
+
+Page 382
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+
+
+TPM_CAP_ALGS – Returns a list of TPMS_ALG_PROPERTIES. Each entry is an algorithm ID and a
+set of properties of the algorithm.
+
+
+
+TPM_CAP_HANDLES – Returns a list of all of the handles within the handle range of the property
+parameter. The range of the returned handles is determined by the handle type (the most-significant
+octet (MSO) of the property). Any of the defined handle types is allowed
+EXAMPLE 4
+
+EXAMPLE 5
+
+
+
+If the MSO of property is TPM_HT_NV_INDEX, then the TPM will return a list of NV Index
+values.
+If the MSO of property is TPM_HT_PCR, then the TPM will return a list of PCR.
+
+For this capability, use of TPM_HT_LOADED_SESSION and TPM_HT_SAVED_SESSION is
+allowed. Requesting handles with a handle type of TPM_HT_LOADED_SESSION will return handles
+for loaded sessions. The returned handle values will have a handle type of either
+TPM_HT_HMAC_SESSION or TPM_HT_POLICY_SESSION. If saved sessions are requested, all
+returned values will have the TPM_HT_HMAC_SESSION handle type because the TPM does not
+track the session type of saved sessions.
+NOTE 2
+
+
+
+TPM_HT_LOADED_SESSION and TPM_HT_HMAC_SESSION have the same value, as do
+TPM_HT_SAVED_SESSION and TPM_HT_POLICY_SESSION. It is not possible to request that
+the TPM return a list of loaded HMAC sessions without including the policy sessions.
+
+TPM_CAP_COMMANDS – Returns a list of the command attributes for all of the commands
+implemented in the TPM, starting with the TPM_CC indicated by the property parameter. If vendor
+specific commands are implemented, the vendor-specific command attribute with the lowest
+commandIndex, is returned after the non-vendor-specific (base) command.
+NOTE 4
+
+The type of the property parameter is a TPM_CC while the type of the returned list is
+TPML_CCA.
+
+
+
+TPM_CAP_PP_COMMANDS – Returns a list of all of the commands currently requiring Physical
+Presence for confirmation of platform authorization. The list will start with the TPM_CC indicated by
+property.
+
+
+
+TPM_CAP_AUDIT_COMMANDS – Returns a list of all of the commands currently set for command
+audit.
+
+
+
+TPM_CAP_PCRS – Returns the current allocation of PCR in a TPML_PCR_SELECTION. The
+property parameter shall be zero. The TPM will always respond to this command with the full PCR
+allocation and moreData will be NO.
+
+
+
+TPM_CAP_TPM_PROPERTIES – Returns a list of tagged properties. The tag is a TPM_PT and the
+property is a 32-bit value. The properties are returned in groups. Each property group is on a 256value boundary (that is, the boundary occurs when the TPM_PT is evenly divisible by 256). The TPM
+will only return values in the same group as the property parameter in the command.
+
+
+
+TPM_CAP_PCR_PROPERTIES – Returns a list of tagged PCR properties. The tag is a
+TPM_PT_PCR and the property is a TPMS_PCR_SELECT.
+
+The input command property is a TPM_PT_PCR (see Part 2 for PCR properties to be requested) that
+specifies the first property to be returned. If propertyCount is greater than 1, the list of properties begins
+with that property and proceeds in TPM_PT_PCR sequence.
+NOTE 5
+
+If the propertyCount selects an unimplemented property, the next higher implemented property
+is returned.
+
+Each item in the list is a TPMS_PCR_SELECT structure that contains a bitmap of all PCR.
+NOTE 6
+
+A PCR index in all banks (all hash algorithms) has the same properties, so the hash algorithm is
+not specified here.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 383
+October 31, 2013
+
+ Part 3: Commands
+
+
+Trusted Platform Module Library
+
+TPM_CAP_TPM_ECC_CURVES – Returns a list of ECC curve identifiers currently available for use
+in the TPM.
+
+The moreData parameter will have a value of YES if there are more values of the requested type that
+were not returned.
+If no next capability exists, the TPM will return a zero-length list and moreData will have a value of NO.
+
+Page 384
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+32.2.2 Command and Response
+Table 193 — TPM2_GetCapability Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_GetCapability
+
+TPM_CAP
+
+capability
+
+group selection; determines the format of the response
+
+UINT32
+
+property
+
+further definition of information
+
+UINT32
+
+propertyCount
+
+number of properties of the indicated type to return
+
+Table 194 — TPM2_GetCapability Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPMI_YES_NO
+
+moreData
+
+flag to indicate if there are more values of this type
+
+TPMS_CAPABILITY_DATA
+
+capabilityData
+
+the capability data
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 385
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+32.2.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "GetCapability_fp.h"
+Error Returns
+TPM_RC_HANDLE
+
+value of property is in an unsupported handle range for the
+TPM_CAP_HANDLES capability value
+
+TPM_RC_VALUE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+invalid capability; or property is not 0 for the TPM_CAP_PCRS
+capability value
+
+TPM_RC
+TPM2_GetCapability(
+GetCapability_In
+GetCapability_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+// Command Output
+// Set output capability type the same as input type
+out->capabilityData.capability = in->capability;
+switch(in->capability)
+{
+case TPM_CAP_ALGS:
+out->moreData = AlgorithmCapGetImplemented((TPM_ALG_ID) in->property,
+in->propertyCount, &out->capabilityData.data.algorithms);
+break;
+case TPM_CAP_HANDLES:
+switch(HandleGetType((TPM_HANDLE) in->property))
+{
+case TPM_HT_TRANSIENT:
+// Get list of handles of loaded transient objects
+out->moreData = ObjectCapGetLoaded((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_PERSISTENT:
+// Get list of handles of persistent objects
+out->moreData = NvCapGetPersistent((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_NV_INDEX:
+// Get list of defined NV index
+out->moreData = NvCapGetIndex((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_LOADED_SESSION:
+// Get list of handles of loaded sessions
+out->moreData = SessionCapGetLoaded((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_ACTIVE_SESSION:
+// Get list of handles of
+out->moreData = SessionCapGetSaved((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+
+Page 386
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+
+Part 3: Commands
+
+break;
+case TPM_HT_PCR:
+// Get list of handles of PCR
+out->moreData = PCRCapGetHandles((TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+case TPM_HT_PERMANENT:
+// Get list of permanent handles
+out->moreData = PermanentCapGetHandles(
+(TPM_HANDLE) in->property,
+in->propertyCount,
+&out->capabilityData.data.handles);
+break;
+default:
+// Unsupported input handle type
+return TPM_RC_HANDLE + RC_GetCapability_property;
+break;
+}
+break;
+case TPM_CAP_COMMANDS:
+out->moreData = CommandCapGetCCList((TPM_CC) in->property,
+in->propertyCount,
+&out->capabilityData.data.command);
+break;
+case TPM_CAP_PP_COMMANDS:
+out->moreData = PhysicalPresenceCapGetCCList((TPM_CC) in->property,
+in->propertyCount, &out->capabilityData.data.ppCommands);
+break;
+case TPM_CAP_AUDIT_COMMANDS:
+out->moreData = CommandAuditCapGetCCList((TPM_CC) in->property,
+in->propertyCount,
+&out->capabilityData.data.auditCommands);
+break;
+case TPM_CAP_PCRS:
+// Input property must be 0
+if(in->property != 0)
+return TPM_RC_VALUE + RC_GetCapability_property;
+out->moreData = PCRCapGetAllocation(in->propertyCount,
+&out->capabilityData.data.assignedPCR);
+break;
+case TPM_CAP_PCR_PROPERTIES:
+out->moreData = PCRCapGetProperties((TPM_PT_PCR) in->property,
+in->propertyCount,
+&out->capabilityData.data.pcrProperties);
+break;
+case TPM_CAP_TPM_PROPERTIES:
+out->moreData = TPMCapGetProperties((TPM_PT) in->property,
+in->propertyCount,
+&out->capabilityData.data.tpmProperties);
+break;
+#ifdef TPM_ALG_ECC
+case TPM_CAP_ECC_CURVES:
+out->moreData = CryptCapGetECCCurve((TPM_ECC_CURVE
+) in->property,
+in->propertyCount,
+&out->capabilityData.data.eccCurves);
+break;
+#endif // TPM_ALG_ECC
+case TPM_CAP_VENDOR_PROPERTY:
+// vendor property is not implemented
+default:
+// Unexpected TPM_CAP value
+return TPM_RC_VALUE;
+break;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 387
+October 31, 2013
+
+ Part 3: Commands
+116
+117
+118
+119
+
+Trusted Platform Module Library
+
+}
+return TPM_RC_SUCCESS;
+}
+
+Page 388
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+32.3
+
+Part 3: Commands
+
+TPM2_TestParms
+
+32.3.1 General Description
+This command is used to check to see if specific combinations of algorithm parameters are supported.
+The TPM will unmarshal the provided TPMT_PUBLIC_PARMS. If the parameters unmarshal correctly,
+then the TPM will return TPM_RC_SUCCESS, indicating that the parameters are valid for the TPM. The
+TPM will return the appropriate unmarshaling error if a parameter is not valid.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 389
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+32.3.2 Command and Response
+Table 195 — TPM2_TestParms Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_TestParms
+
+TPMT_PUBLIC_PARMS
+
+parameters
+
+algorithm parameters to be validated
+
+Table 196 — TPM2_TestParms Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 390
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+32.3.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+#include "InternalRoutines.h"
+#include "TestParms_fp.h"
+
+TPM_RC
+TPM2_TestParms(
+TestParms_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+// Input parameter is not reference in command action
+in = NULL;
+// The parameters are tested at unmarshal process.
+// action
+return TPM_RC_SUCCESS;
+
+We do nothing in command
+
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 391
+October 31, 2013
+
+ Part 3: Commands
+
+33
+
+Trusted Platform Module Library
+
+Non-volatile Storage
+
+33.1
+
+Introduction
+
+The NV commands are used to create, update, read, and delete allocations of space in NV memory.
+Before an Index may be used, it must be defined (TPM2_NV_DefineSpace()).
+An Index may be modified if the proper write authorization is provided or read if the proper read
+authorization is provided. Different controls are available for reading and writing.
+An Index may have an Index-specific authValue and authPolicy. The authValue may be used to authorize
+reading if TPMA_NV_AUTHREAD is SET and writing if TPMA_NV_AUTHREAD is SET. The authPolicy
+may be used to authorize reading if TPMA_NV_POLICYREAD is SET and writing if
+TPMA_NV_POLICYWRITE is SET.
+TPMA_NV_PPREAD and TPMA_NV_PPWRITE indicate if reading or writing of the NV Index may be
+authorized by platformAuth or platformPolicy.
+TPMA_NV_OWNERREAD and TPMA_NV_OWNERWRITE indicate if reading or writing of the NV Index
+may be authorized by ownerAuth or ownerPolicy.
+If an operation on an NV index requires authorization, and the authHandle parameter is the handle of an
+NV Index, then the nvIndex parameter must have the same value or the TPM will return
+TPM_RC_NV_AUTHORIZATION.
+NOTE 1
+
+This check ensures that the authorization that was provided is associated with the NV Index being
+authorized.
+
+For creating an Index, ownerAuth may not be used if shEnable is CLEAR and platformAuth may not be
+used if phEnableNV is CLEAR.
+If an Index was defined using platformAuth, then that Index is not accessible when phEnableNV is
+CLEAR. If an Index was defined using ownerAuth, then that Index is not accessible when shEnable is
+CLEAR.
+For read access control, any combination of TPMA_NV_PPREAD, TPMA_NV_OWNERREAD,
+TPMA_NV_AUTHREAD, or TPMA_NV_POLICYREAD is allowed as long as at least one is SET.
+For write access control, any combination of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE,
+TPMA_NV_AUTHWRITE, or TPMA_NV_POLICYWRITE is allowed as long as at least one is SET.
+If an Index has been defined and not written, then any operation on the NV Index that requires read
+authorization will fail (TPM_RC_NV_INITIALIZED). This check may be made before or after other
+authorization checks but shall be performed before checking the NV Index authValue. An authorization
+failure due to the NV Index not having been written shall not be logged by the dictionary attack logic.
+If TPMA_NV_CLEAR_STCLEAR is SET, then the TPMA_NV_WRITTEN will be CLEAR on each
+TPM2_Startup(TPM_SU_CLEAR).
+TPMA_NV_CLEAR_STCLEAR
+shall
+not
+be
+SET
+if
+TPMA_NV_COUNTER is SET.
+The code in the “Detailed Actions” clause of each command is written to interface with an implementationdependent library that allows access to NV memory. The actions assume no specific layout of the
+structure of the NV data.
+Only one NV Index may be directly referenced in a command.
+NOTE 2
+
+This means that, if authHandle references an NV Index, then nvIndex will have the same value.
+However, this does not limit the number of changes that may occur as side effects. For example, any
+number of NV Indexes might be relocated as a result of deleting or adding a NV Ind ex.
+
+Page 392
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.2
+
+Part 3: Commands
+
+NV Counters
+
+When an Index has the TPMA_NV_COUNTER attribute set, it behaves as a monotonic counter and may
+only be updated using TPM2_NV_Increment().
+When an NV counter is created, the TPM shall initialize the 8-octet counter value with a number that is
+greater than any count value for any NV counter on the TPM since the time of TPM manufacture.
+An NV counter may be defined with the TPMA_NV_ORDERLY attribute to indicate that the NV Index is
+expected to be modified at a high frequency and that the data is only required to persist when the TPM
+goes through an orderly shutdown process. The TPM may update the counter value in RAM and
+occasionally update the non-volatile version of the counter. An orderly shutdown is one occasion to
+update the non-volatile count. If the difference between the volatile and non-volatile version of the counter
+becomes as large as MAX_ORDERLY_COUNT, this shall be another occasion for updating the nonvolatile count.
+Before an NV counter can be used, the TPM shall validate that the count is not less than a previously
+reported value. If the TPMA_NV_ORDERLY attribute is not SET, or if the TPM experienced an orderly
+shutdown, then the count is assumed to be correct. If the TPMA_NV_ORDERLY attribute is SET, and the
+TPM shutdown was not orderly, then the TPM shall OR MAX_ORDERLY_COUNT to the contents of the
+non-volatile counter and set that as the current count.
+NOTE 1
+
+Because the TPM would have updated the NV Index if the difference between the count values was
+equal to MAX_ORDERLY_COUNT + 1, the highest value that could have been in the NV Index is
+MAX_ORDERLY_COUNT so it is safe to restore that value.
+
+NOTE 2
+
+The TPM may implement the RAM portion of the counter such that the effective value of the NV
+counter is the sum of both the volatile and non-volatile parts. If so, then the TPM may initialize the
+RAM version of the counter to MAX_ORDERLY_COUNT and no update of NV is necessary.
+
+NOTE 3
+
+When a new NV counter is created, the TPM may search all the counters to determine which has the
+highest value. In this search, the TPM would use the sum of the non -volatile and RAM portions of
+the counter. The RAM portion of the counter shall be properly initialized to reflect shutdown p rocess
+(orderly or not) of the TPM.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 393
+October 31, 2013
+
+ Part 3: Commands
+
+33.3
+
+Trusted Platform Module Library
+
+TPM2_NV_DefineSpace
+
+33.3.1 General Description
+This command defines the attributes of an NV Index and causes the TPM to reserve space to hold the
+data associated with the NV Index. If a definition already exists at the NV Index, the TPM will return
+TPM_RC_NV_DEFINED.
+The TPM will return TPM_RC_ATTRIBUTES if more
+TPMA_NV_BITS, or TPMA_NV_EXTEND is SET in publicInfo.
+NOTE
+
+than
+
+one
+
+of
+
+TPMA_NV_COUNTER,
+
+It is not required that any of these three attributes be set.
+
+The TPM shall return TPM_RC_ATTRIBUTES if TPMA_NV_WRITTEN, TPM_NV_READLOCKED, or
+TPMA_NV_WRITELOCKED is SET.
+If TPMA_NV_COUNTER or TPMA_NV_BITS is SET, then publicInfo→dataSize shall be set to eight (8) or
+the TPM shall return TPM_RC_SIZE.
+If TPMA_NV_EXTEND is SET, then publicInfo→dataSize shall match the digest size of the
+publicInfo.nameAlg or the TPM shall return TPM_RC_SIZE.
+If the NV Index is an ordinary Index and publicInfo→dataSize is larger than supported by the TPM
+implementation then the TPM shall return TPM_RC_SIZE.
+NOTE
+
+The limit for the data size may vary according to the type of the index. For example, if the index is
+has TPMA_NV_ORDERLY SET, then the maximum size of an ordin ary NV Index may be less than
+the size of an ordinary NV Index that has TPMA_NV_ORDERLY CLEAR.
+
+At least one of TPMA_NV_PPREAD, TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD,
+TPMA_NV_POLICYREAD shall be SET or the TPM shall return TPM_RC_ATTRIBUTES.
+
+or
+
+At least one of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, or
+TPMA_NV_POLICYWRITE shall be SET or the TPM shall return TPM_RC_ATTRIBUTES.
+If TPMA_NV_CLEAR_STCLEAR is SET, then TPMA_NV_COUNTER shall be CLEAR or the TPM shall
+return TPM_RC_ATTRIBUTES.
+If platformAuth/platformPolicy is used for authorization, then TPMA_NV_PLATFORMCREATE shall be
+SET in publicInfo. If ownerAuth/ownerPolicy is used for authorization, TPMA_NV_PLATFORMCREATE
+shall be CLEAR in publicInfo. If TPMA_NV_PLATFORMCREATE is not set correctly for the authorization,
+the TPM shall return TPM_RC_ATTRIBUTES.
+If TPMA_NV_POLICY_DELETE is SET, then the authorization shall be with platformAuth or the TPM
+shall return TPM_RC_ATTRIBUTES.
+If the implementation does not support TPM2_NV_Increment(),
+TPM_RC_ATTRIBUTES if TPMA_NV_COUNTER is SET.
+
+the
+
+TPM
+
+shall
+
+return
+
+If the implementation does not support TPM2_NV_SetBits(),
+TPM_RC_ATTRIBUTES if TPMA_NV_BITS is SET.
+
+the
+
+TPM
+
+shall
+
+return
+
+If the implementation does not support TPM2_NV_Extend(),
+TPM_RC_ATTRIBUTES if TPMA_NV_EXTEND is SET.
+
+the
+
+TPM
+
+shall
+
+return
+
+If the implementation does not support TPM2_NV_UndefineSpaceSpecial(), the TPM shall return
+TPM_RC_ATTRIBUTES if TPMA_NV_POLICY_DELETE is SET.
+After the successful completion of this command, the NV Index exists but TPMA_NV_WRITTEN will be
+CLEAR. Any access of the NV data will return TPM_RC_NV_UINITIALIZED.
+
+Page 394
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+In some implementations, an NV Index with the TPMA_NV_COUNTER attribute may require special TPM
+resources that provide higher endurance than regular NV. For those implementations, if this command
+fails because of lack of resources, the TPM will return TPM_RC_NV_SPACE.
+The value of auth is saved in the created structure. The size of auth is limited to be no larger than the size
+of the digest produced by the NV Index's nameAlg (TPM_RC_SIZE).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 395
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.3.2 Command and Response
+Table 197 — TPM2_NV_DefineSpace Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_DefineSpace {NV}
+
+TPMI_RH_PROVISION
+
+@authHandle
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPM2B_AUTH
+
+auth
+
+the authorization value
+
+TPM2B_NV_PUBLIC
+
+publicInfo
+
+the public parameters of the NV area
+
+Table 198 — TPM2_NV_DefineSpace Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 396
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.3.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "NV_DefineSpace_fp.h"
+Error Returns
+TPM_RC_NV_ATTRIBUTES
+
+attributes of the index are not consistent
+
+TPM_RC_NV_DEFINED
+
+index already exists
+
+TPM_RC_HIERARCHY
+
+for authorizations using TPM_RH_PLATFORM phEnable_NV is
+clear.
+
+TPM_RC_NV_SPACE
+
+Insufficient space for the index
+
+TPM_RC_SIZE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+'auth->size' or 'publicInfo->authPolicy. size' is larger than the digest
+size of 'publicInfo->nameAlg', or 'publicInfo->dataSize' is not
+consistent with 'publicInfo->attributes'.
+
+TPM_RC
+TPM2_NV_DefineSpace(
+NV_DefineSpace_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+TPMA_NV
+UINT16
+
+result;
+attributes;
+nameSize;
+
+nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg);
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation
+// If an index is being created by the owner and shEnable is
+// clear, then we would not reach this point because ownerAuth
+// can't be given when shEnable is CLEAR. However, if phEnable
+// is SET but phEnableNV is CLEAR, we have to check here
+if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
+return TPM_RC_HIERARCHY + RC_NV_DefineSpace_authHandle;
+attributes = in->publicInfo.t.nvPublic.attributes;
+//TPMS_NV_PUBLIC validation.
+// Counters and bit fields must have a size of 8
+if (
+(attributes.TPMA_NV_COUNTER == SET || attributes.TPMA_NV_BITS == SET)
+&& (in->publicInfo.t.nvPublic.dataSize != 8))
+return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
+// check that the authPolicy consistent with hash algorithm
+if(
+in->publicInfo.t.nvPublic.authPolicy.t.size != 0
+&& in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize)
+return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
+// make sure that the authValue is not too large
+MemoryRemoveTrailingZeros(&in->auth);
+if(in->auth.t.size > nameSize)
+return TPM_RC_SIZE + RC_NV_DefineSpace_auth;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 397
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+
+Trusted Platform Module Library
+
+//TPMA_NV validation.
+// Locks may not be SET and written cannot be SET
+if(
+attributes.TPMA_NV_WRITTEN == SET
+|| attributes.TPMA_NV_WRITELOCKED == SET
+|| attributes.TPMA_NV_READLOCKED == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// There must be a way to read the index
+if(
+attributes.TPMA_NV_OWNERREAD == CLEAR
+&& attributes.TPMA_NV_PPREAD == CLEAR
+&& attributes.TPMA_NV_AUTHREAD == CLEAR
+&& attributes.TPMA_NV_POLICYREAD == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// There must be a way to write the index
+if(
+attributes.TPMA_NV_OWNERWRITE == CLEAR
+&& attributes.TPMA_NV_PPWRITE == CLEAR
+&& attributes.TPMA_NV_AUTHWRITE == CLEAR
+&& attributes.TPMA_NV_POLICYWRITE == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// Make sure that no attribute is used that is not supported by the proper
+// command
+#if CC_NV_Increment == NO
+if( attributes.TPMA_NV_COUNTER == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+#if CC_NV_SetBits == NO
+if( attributes.TPMA_NV_BITS == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+#if CC_NV_Extend == NO
+if( attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+#if CC_NV_UndefineSpaceSpecial == NO
+if( attributes.TPMA_NV_POLICY_DELETE == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+#endif
+// Can be COUNTER or BITS or EXTEND but not more than one
+if( attributes.TPMA_NV_COUNTER == SET
+&& attributes.TPMA_NV_BITS == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+if(
+attributes.TPMA_NV_COUNTER == SET
+&& attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+if(
+attributes.TPMA_NV_BITS == SET
+&& attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// An index with TPMA_NV_CLEAR_STCLEAR can't be a counter
+if(
+attributes.TPMA_NV_CLEAR_STCLEAR == SET
+&& attributes.TPMA_NV_COUNTER == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// The index is allowed to have one of GLOBALLOCK or WRITEDEFINE SET
+if(
+attributes.TPMA_NV_GLOBALLOCK == SET
+&& attributes.TPMA_NV_WRITEDEFINE == SET)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// Make sure that the creator of the index can delete the index
+
+Page 398
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+
+if(
+
+Part 3: Commands
+
+(
+
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET
+&& in->authHandle == TPM_RH_OWNER
+)
+|| (
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR
+&& in->authHandle == TPM_RH_PLATFORM
+)
+)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
+
+// If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
+// the platform
+if(
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET
+&& TPM_RH_PLATFORM != in->authHandle
+)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// If the NV index is used as a PCR, the data size must match the digest
+// size
+if(
+in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET
+&& in->publicInfo.t.nvPublic.dataSize != nameSize
+)
+return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
+// See if the index is already defined.
+if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex))
+return TPM_RC_NV_DEFINED;
+// Internal Data Update
+// define the space. A TPM_RC_NV_SPACE error may be returned at this point
+result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth);
+if(result != TPM_RC_SUCCESS)
+return result;
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 399
+October 31, 2013
+
+ Part 3: Commands
+
+33.4
+
+Trusted Platform Module Library
+
+TPM2_NV_UndefineSpace
+
+33.4.1 General Description
+This command removes an Index from the TPM.
+If nvIndex is not defined, the TPM shall return TPM_RC_HANDLE.
+If nvIndex references an Index that has its TPMA_NV_PLATFORMCREATE attribute SET, the TPM shall
+return TPM_RC_NV_AUTHORITY unless platformAuth is provided.
+NOTE
+
+An Index with TPMA_NV_PLATFORMCREATE CLEAR may be deleted with platformAuth as long as
+shEnable is SET. If shEnable is CLEAR, indexes created using ownerAuth are not accessible even
+for deletion by the platform.
+
+Page 400
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.4.2 Command and Response
+Table 199 — TPM2_NV_UndefineSpace Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_UndefineSpace {NV}
+
+TPMI_RH_PROVISION
+
+@authHandle
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to remove from NV space
+Auth Index: None
+
+Table 200 — TPM2_NV_UndefineSpace Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 401
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.4.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "NV_UndefineSpace_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+TPMA_NV_POLICY_DELETE is SET in the Index referenced by
+nvIndex so this command may not be used to delete this Index (see
+TPM2_NV_UndefineSpaceSpecial())
+
+TPM_RC_NV_AUTHORIZATION
+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
+33
+34
+35
+36
+37
+38
+
+Meaning
+
+attempt to use ownerAuth to delete an index created by the platform
+
+TPM_RC
+TPM2_NV_UndefineSpace(
+NV_UndefineSpace_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET
+if(SET == nvIndex.publicArea.attributes.TPMA_NV_POLICY_DELETE)
+return TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex;
+// The owner may only delete an index that was defined with ownerAuth. The
+// platform may delete an index that was created with either auth.
+if(
+in->authHandle == TPM_RH_OWNER
+&& nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET)
+return TPM_RC_NV_AUTHORIZATION;
+// Internal Data Update
+// Call implementation dependent internal routine to delete NV index
+NvDeleteEntity(in->nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Page 402
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.5
+
+Part 3: Commands
+
+TPM2_NV_UndefineSpaceSpecial
+
+33.5.1 General Description
+This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE
+SET.
+This command requires that the policy of the NV Index be satisfied before the NV Index may be deleted.
+Because administrative role is required, the policy must contain a command that sets the policy command
+code to TPM_CC_NV_UndefineSpaceSpecial. This indicates that the policy that is being used is a policy
+that is for this command, and not a policy that would approve another use. That is, authority to use an
+object does not grant authority to undefined the object.
+If nvIndex is not defined, the TPM shall return TPM_RC_HANDLE.
+If
+nvIndex
+references
+an
+Index
+that
+has
+its
+TPMA_NV_PLATFORMCREATE
+TPMA_NV_POLICY_DELETE attribute CLEAR, the TPM shall return TPM_RC_NV_ATTRIBUTES.
+NOTE
+
+or
+
+An
+Index
+with
+TPMA_NV_PLATFORMCREATE
+CLEAR
+may
+be
+deleted
+with
+TPM2_UndefineSpace()as long as shEnable is SET. If shEnable is CLEAR, indexes created using
+ownerAuth are not accessible even for deletion by the platform .
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 403
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.5.2 Command and Response
+Table 201 — TPM2_NV_UndefineSpaceSpecial Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_UndefineSpaceSpecial {NV}
+
+TPMI_RH_NV_INDEX
+
+@nvIndex
+
+Index to be deleted
+Auth Index: 1
+Auth Role: ADMIN
+
+TPMI_RH_PLATFORM
+
+@platform
+
+TPM_RH_PLATFORM + {PP}
+Auth Index: 2
+Auth Role: USER
+
+Table 202 — TPM2_NV_UndefineSpaceSpecial Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 404
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.5.3 Detailed Actions
+1
+2
+
+#include "InternalRoutines.h"
+#include "NV_UndefineSpaceSpecial_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+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
+33
+
+Meaning
+TPMA_NV_POLICY_DELETE is not SET in the Index referenced by
+nvIndex
+
+TPM_RC
+TPM2_NV_UndefineSpaceSpecial(
+NV_UndefineSpaceSpecial_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET
+if(CLEAR == nvIndex.publicArea.attributes.TPMA_NV_POLICY_DELETE)
+return TPM_RC_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex;
+// Internal Data Update
+// Call implementation dependent internal routine to delete NV index
+NvDeleteEntity(in->nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 405
+October 31, 2013
+
+ Part 3: Commands
+
+33.6
+
+Trusted Platform Module Library
+
+TPM2_NV_ReadPublic
+
+33.6.1 General Description
+This command is used to read the public area and Name of an NV Index. The public area of an Index is
+not privacy-sensitive and no authorization is required to read this data.
+
+Page 406
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.6.2 Command and Response
+Table 203 — TPM2_NV_ReadPublic Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_ReadPublic
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index
+Auth Index: None
+
+Table 204 — TPM2_NV_ReadPublic Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_NV_PUBLIC
+
+nvPublic
+
+the public area of the NV Index
+
+TPM2B_NAME
+
+nvName
+
+the Name of the nvIndex
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 407
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.6.3 Detailed Actions
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+
+#include "InternalRoutines.h"
+#include "NV_ReadPublic_fp.h"
+
+TPM_RC
+TPM2_NV_ReadPublic(
+NV_ReadPublic_In
+NV_ReadPublic_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+NV_INDEX
+
+nvIndex;
+
+// Command Output
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Copy data to output
+out->nvPublic.t.nvPublic = nvIndex.publicArea;
+// Compute NV name
+out->nvName.t.size = NvGetName(in->nvIndex, &out->nvName.t.name);
+return TPM_RC_SUCCESS;
+}
+
+Page 408
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.7
+
+Part 3: Commands
+
+TPM2_NV_Write
+
+33.7.1 General Description
+This command writes a value to an area in NV memory that was previously defined by
+TPM2_NV_DefineSpace().
+Proper authorizations are required for this command as determined by TPMA_NV_PPWRITE;
+TPMA_NV_OWNERWRITE; TPMA_NV_AUTHWRITE; and, if TPMA_NV_POLICY_WRITE is SET, the
+authPolicy of the NV Index.
+If the TPMA_NV_WRITELOCKED attribute of the NV Index is SET, then the TPM shall return
+TPM_RC_NV_LOCKED.
+NOTE 1
+
+If authorization sessions are present, they are checked before checks to see if writes to the NV
+Index are locked.
+
+If TPMA_NV_COUNTER, TPMA_NV_BITS or TPMA_NV_EXTEND of the NV Index is SET, then the
+TPM shall return TPM_RC_NV_ATTRIBUTE.
+If the size of the data parameter plus the offset parameter adds to a value that is greater than the size of
+the NV Index data, the TPM shall return TPM_RC_NV_RANGE and not write any data to the NV Index.
+If the TPMA_NV_WRITEALL attribute of the NV Index is SET, then the TPM shall return
+TPM_RC_NV_RANGE if the size of the data parameter of the command is not the same as the data field
+of the NV Index.
+If all checks succeed, the TPM will merge the data.size octets of data.buffer value into the nvIndex→data
+starting at nvIndex→data[offset]. If the NV memory is implemented with a technology that has endurance
+limitations, the TPM shall check that the merged data is different from the current contents of the NV
+Index and only perform a write to NV memory if they differ.
+After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
+NOTE 2
+
+Once SET, TPMA_NV_WRITTEN remains SET until the NV Index is undefined or the NV Index is
+cleared.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 409
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.7.2 Command and Response
+Table 205 — TPM2_NV_Write Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Write {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index of the area to write
+Auth Index: None
+
+TPM2B_MAX_NV_BUFFER
+
+data
+
+the data to write
+
+UINT16
+
+offset
+
+the offset into the NV Area
+
+Table 206 — TPM2_NV_Write Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 410
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.7.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "NV_Write_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+Index referenced by nvIndex has either TPMA_NV_BITS,
+TPMA_NV_COUNTER, or TPMA_NV_EVENT attribute SET
+
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+
+Index referenced by nvIndex is write locked
+
+TPM_RC_NV_RANGE
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+
+Meaning
+
+if TPMA_NV_WRITEALL is SET then the write is not the size of the
+Index referenced by nvIndex; otherwise, the write extends beyond the
+limits of the Index
+
+TPM_RC
+TPM2_NV_Write(
+NV_Write_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+NV_INDEX
+TPM_RC
+
+nvIndex;
+result;
+
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// common access checks. NvWrtieAccessChecks() may return
+// TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Bits index, extend index or counter index may not be updated by
+// TPM2_NV_Write
+if(
+nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
+|| nvIndex.publicArea.attributes.TPMA_NV_BITS == SET
+|| nvIndex.publicArea.attributes.TPMA_NV_EXTEND == SET)
+return TPM_RC_ATTRIBUTES;
+// Too much data
+if((in->data.t.size + in->offset) > nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// If this index requires a full sized write, make sure that input range is
+// full sized
+if(
+nvIndex.publicArea.attributes.TPMA_NV_WRITEALL == SET
+&& in->data.t.size < nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// Internal Data Update
+// Perform the write. This called routine will SET the TPMA_NV_WRITTEN
+// attribute if it has not already been SET. If NV isn't available, an error
+// will be returned.
+return NvWriteIndexData(in->nvIndex, &nvIndex, in->offset,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 411
+October 31, 2013
+
+ Part 3: Commands
+46
+47
+48
+
+Trusted Platform Module Library
+in->data.t.size, in->data.t.buffer);
+
+}
+
+Page 412
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.8
+
+Part 3: Commands
+
+TPM2_NV_Increment
+
+33.8.1 General Description
+This command is used to increment the value in an NV Index that has TPMA_NV_COUNTER SET. The
+data value of the NV Index is incremented by one.
+NOTE 1
+
+The NV Index counter is an unsigned value.
+
+If TPMA_NV_COUNTER
+TPM_RC_ATTRIBUTES.
+
+is
+
+not
+
+SET
+
+in
+
+the
+
+indicated
+
+NV
+
+Index,
+
+the
+
+TPM
+
+shall
+
+return
+
+If TPMA_NV_WRITELOCKED is SET, the TPM shall return TPM_RC_NV_LOCKED.
+If TPMA_NV_WRITTEN is CLEAR, it will be SET.
+If TPMA_NV_ORDERLY is SET, and the difference between the volatile and non-volatile versions of this
+field is greater than MAX_ORDERLY_COUNT, then the non-volatile version of the counter is updated.
+NOTE 2
+
+If a TPM implements TPMA_NV_ORDERLY and an Index is defined with TPMA_NV_ORDERLY and
+TPM_NV_COUNTER both SET, then in the Event of a non-orderly shutdown, the non-volatile value
+for the counter Index will be advanced by MAX_ORDERLY_COUNT at the next TPM2_Startup().
+
+NOTE 3
+
+An allowed implementation would keep a counter value in NV and a resettable counter in RAM. The
+reported value of the NV Index would be the sum of the two values. When the RAM count increments
+past the maximum allowed value (MAX_ORDERLY_COUNT), the non-volatile version of the count is
+updated with the sum of the values and the RAM count is reset to zero.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 413
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.8.2 Command and Response
+Table 207 — TPM2_NV_Increment Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Increment {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to increment
+Auth Index: None
+
+Table 208 — TPM2_NV_Increment Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 414
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.8.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "NV_Increment_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+NV index is not a counter
+
+TPM_RC_NV_AUTHORIZATION
+
+authorization failure
+
+TPM_RC_NV_LOCKED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+Index is write locked
+
+TPM_RC
+TPM2_NV_Increment(
+NV_Increment_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+UINT64
+
+result;
+nvIndex;
+countValue;
+
+// Input Validation
+// Common access checks, a TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Make sure that this is a counter
+if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER != SET)
+return TPM_RC_ATTRIBUTES + RC_NV_Increment_nvIndex;
+// Internal Data Update
+// If counter index is not been written, initialize it
+if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+countValue = NvInitialCounter();
+else
+// Read NV data in native format for TPM CPU.
+NvGetIntIndexData(in->nvIndex, &nvIndex, &countValue);
+// Do the increment
+countValue++;
+// If this is an orderly counter that just rolled over, need to be able to
+// write to NV to proceed. This check is done here, because NvWriteIndexData()
+// does not see if the update is for counter rollover.
+if(
+nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET
+&& (countValue & MAX_ORDERLY_COUNT) == 0)
+{
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Need to force an NV update
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 415
+October 31, 2013
+
+ Part 3: Commands
+52
+53
+54
+55
+56
+57
+58
+59
+60
+
+Trusted Platform Module Library
+
+g_updateNV = TRUE;
+}
+// Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may
+// be returned at this point. If necessary, this function will set the
+// TPMA_NV_WRITTEN attribute
+return NvWriteIndexData(in->nvIndex, &nvIndex, 0, 8, &countValue);
+}
+
+Page 416
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.9
+
+Part 3: Commands
+
+TPM2_NV_Extend
+
+33.9.1 General Description
+This command extends a value to an area in NV memory that was previously defined by
+TPM2_NV_DefineSpace.
+If TPMA_NV_EXTEND is not SET, then the TPM shall return TPM_RC_ATTRIBUTES.
+Proper write authorizations are required for this command as determined by TPMA_NV_PPWRITE,
+TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, and the authPolicy of the NV Index.
+After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
+NOTE 1
+
+Once SET, TPMA_NV_WRITTEN remains SET until the NV Index is undefined or the NV Index is
+cleared.
+
+If the TPMA_NV_WRITELOCKED attribute of the NV Index is SET, then the TPM shall return
+TPM_RC_NV_LOCKED.
+NOTE 2
+
+If authorization sessions are present, they are checked before checks to see if writes to the NV
+Index are locked.
+
+The data.buffer parameter may be larger than the defined size of the NV Index.
+The Index will be updated by:
+
+nvIndex→datanew ≔ HnameAkg(nvIndex→dataold || data.buffer)
+
+(39)
+
+where
+
+HnameAkg()
+
+the hash algorithm indicated in nvIndex→nameAlg
+
+nvIndex→data
+
+the value of the data field in the NV Index
+
+data.buffer
+
+the data buffer of the command parameter
+
+NOTE 3
+
+If TPMA_NV_WRITTEN is CLEAR, then nvIndex→data is a Zero Digest.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 417
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.9.2 Command and Response
+Table 209 — TPM2_NV_Extend Command
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Extend {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to extend
+Auth Index: None
+
+TPM2B_MAX_NV_BUFFER
+
+data
+
+the data to extend
+
+Table 210 — TPM2_NV_Extend Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 418
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.9.3 Detailed Actions
+1
+2
+3
+
+#include "InternalRoutines.h"
+#include "NV_Extend_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+the TPMA_NV_EXTEND attribute is not SET in the Index referenced
+by nvIndex
+
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+the Index referenced by nvIndex is locked for writing
+
+TPM_RC
+TPM2_NV_Extend(
+NV_Extend_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+TPM2B_DIGEST
+TPM2B_DIGEST
+HASH_STATE
+
+oldDigest;
+newDigest;
+hashState;
+
+// Input Validation
+// Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
+// or TPM_RC_NV_LOCKED
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Make sure that this is an extend index
+if(nvIndex.publicArea.attributes.TPMA_NV_EXTEND != SET)
+return TPM_RC_ATTRIBUTES + RC_NV_Extend_nvIndex;
+// If the Index is not-orderly, or if this is the first write, NV will
+// need to be updated.
+if(
+nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == CLEAR
+|| nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+{
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Internal Data Update
+// Perform the write.
+oldDigest.t.size = CryptGetHashDigestSize(nvIndex.publicArea.nameAlg);
+if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
+{
+NvGetIndexData(in->nvIndex, &nvIndex, 0,
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 419
+October 31, 2013
+
+ Part 3: Commands
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+
+Trusted Platform Module Library
+
+oldDigest.t.size, oldDigest.t.buffer);
+}
+else
+{
+MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size);
+}
+// Start hash
+newDigest.t.size = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState);
+// Adding old digest
+CryptUpdateDigest2B(&hashState, &oldDigest.b);
+// Adding new data
+CryptUpdateDigest2B(&hashState, &in->data.b);
+// Complete hash
+CryptCompleteHash2B(&hashState, &newDigest.b);
+// Write extended hash back.
+// Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary
+return NvWriteIndexData(in->nvIndex, &nvIndex, 0,
+newDigest.t.size, newDigest.t.buffer);
+}
+
+Page 420
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.10 TPM2_NV_SetBits
+33.10.1
+
+General Description
+
+This command is used to SET bits in an NV Index that was created as a bit field. Any number of bits from
+0 to 64 may be SET. The contents of data are ORed with the current contents of the NV Index starting at
+offset. The checks on data and offset are the same as for TPM2_NV_Write.
+If TPMA_NV_WRITTEN is not SET, then, for the purposes of this command, the NV Index is considered
+to contain all zero bits and data is OR with that value.
+If TPMA_NV_BITS is not SET, then the TPM shall return TPM_RC_ATTRIBUTES.
+After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
+NOTE
+
+TPMA_NV_WRITTEN will be SET even if no bits were SET.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 421
+October 31, 2013
+
+ Part 3: Commands
+
+33.10.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 211 — TPM2_NV_SetBits Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_SetBits {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+NV Index of the area in which the bit is to be set
+Auth Index: None
+
+UINT64
+
+bits
+
+the data to OR with the current contents
+
+Table 212 — TPM2_NV_SetBits Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 422
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.10.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_SetBits_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+the TPMA_NV_BITS attribute is not SET in the Index referenced by
+nvIndex
+
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+Meaning
+
+the Index referenced by nvIndex is locked for writing
+
+TPM_RC
+TPM2_NV_SetBits(
+NV_SetBits_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+UINT64
+
+result;
+nvIndex;
+bitValue;
+
+// Input Validation
+// Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
+// or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Make sure that this is a bit field
+if(nvIndex.publicArea.attributes.TPMA_NV_BITS != SET)
+return TPM_RC_ATTRIBUTES + RC_NV_SetBits_nvIndex;
+// If the Index is not-orderly, or if this is the first write, NV will
+// need to be updated.
+if(
+nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == CLEAR
+|| nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+{
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Internal Data Update
+// If index is not been written, initialize it
+if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
+bitValue = 0;
+else
+// Read index data
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 423
+October 31, 2013
+
+ Part 3: Commands
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+
+Trusted Platform Module Library
+
+NvGetIntIndexData(in->nvIndex, &nvIndex, &bitValue);
+// OR in the new bit setting
+bitValue |= in->bits;
+// Write index data back. If necessary, this function will SET
+// TPMA_NV_WRITTEN.
+return NvWriteIndexData(in->nvIndex, &nvIndex, 0, 8, &bitValue);
+}
+
+Page 424
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.11 TPM2_NV_WriteLock
+33.11.1
+
+General Description
+
+If the TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR attributes of an NV location are SET,
+then this command may be used to inhibit further writes of the NV Index.
+Proper write authorization is required for this command as determined by TPMA_NV_PPWRITE,
+TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, and the authPolicy of the NV Index.
+It is not an error if TPMA_NV_WRITELOCKED for the NV Index is already SET.
+If neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR of the NV Index is SET, then the
+TPM shall return TPM_RC_ATTRIBUTES.
+If the command is properly authorized and TPMA_NV_WRITE_STCLEAR or TPMA_NV_WRITEDEFINE
+is SET, then the TPM shall SET TPMA_NV_WRITELOCKED for the NV Index.
+TPMA_NV_WRITELOCKED will be clear on the next TPM2_Startup(TPM_SU_CLEAR) unless
+TPMA_NV_WRITEDEFINE is SET.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 425
+October 31, 2013
+
+ Part 3: Commands
+
+33.11.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 213 — TPM2_NV_WriteLock Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_WriteLock {NV}
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index of the area to lock
+Auth Index: None
+
+Table 214 — TPM2_NV_WriteLock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 426
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.11.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_WriteLock_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+neither TPMA_NV_WRITEDEFINE nor
+TPMA_NV_WRITE_STCLEAR is SET in Index referenced by
+nvIndex
+
+TPM_RC_NV_AUTHORIZATION
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+Meaning
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to write to the Index referenced by nvIndex
+
+TPM_RC
+TPM2_NV_WriteLock(
+NV_WriteLock_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Input Validation:
+// Common write access checks, a TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_NV_AUTHORIZATION)
+return TPM_RC_NV_AUTHORIZATION;
+// If write access failed because the index is already locked, then it is
+// no error.
+return TPM_RC_SUCCESS;
+}
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// if non of TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR is set, the index
+// can not be write-locked
+if(
+nvIndex.publicArea.attributes.TPMA_NV_WRITEDEFINE == CLEAR
+&& nvIndex.publicArea.attributes.TPMA_NV_WRITE_STCLEAR == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_WriteLock_nvIndex;
+// Internal Data Update
+// Set the WRITELOCK attribute
+nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET;
+// Write index info back
+NvWriteIndexInfo(in->nvIndex, &nvIndex);
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 427
+October 31, 2013
+
+ Part 3: Commands
+51
+52
+
+Trusted Platform Module Library
+
+return TPM_RC_SUCCESS;
+}
+
+Page 428
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.12 TPM2_NV_GlobalWriteLock
+33.12.1
+
+General Description
+
+The command will SET TPMA_NV_WRITELOCKED
+TPMA_NV_GLOBALLOCK attribute SET.
+
+for
+
+all
+
+indexes
+
+that
+
+have
+
+their
+
+If an Index has both TPMA_NV_WRITELOCKED and TPMA_NV_WRITEDEFINE SET, then this
+command will permanently lock the NV Index for writing.
+NOTE
+
+If an Index is defined with TPMA_NV_GLOBALLOCK SET, then the global lock does not apply until
+the next time this command is executed.
+
+This command requires either platformAuth/platformPolicy or ownerAuth/ownerPolicy.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 429
+October 31, 2013
+
+ Part 3: Commands
+
+33.12.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 215 — TPM2_NV_GlobalWriteLock Command
+
+Type
+
+Name
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_GlobalWriteLock
+
+TPMI_RH_PROVISION
+
+@authHandle
+
+TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+Auth Index: 1
+Auth Role: USER
+
+Description
+
+Table 216 — TPM2_NV_GlobalWriteLock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 430
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.12.3
+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
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_GlobalWriteLock_fp.h"
+
+TPM_RC
+TPM2_NV_GlobalWriteLock(
+NV_GlobalWriteLock_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+
+result;
+
+// Input parameter is not reference in command action
+in = NULL; // to silence compiler warnings.
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+// Internal Data Update
+// Implementation dependent method of setting the global lock
+NvSetGlobalLock();
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 431
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.13 TPM2_NV_Read
+33.13.1
+
+General Description
+
+This command reads a
+TPM2_NV_DefineSpace().
+
+value
+
+from
+
+an
+
+area
+
+in
+
+NV
+
+memory
+
+previously
+
+defined
+
+by
+
+Proper authorizations are required for this command as determined by TPMA_NV_PPREAD,
+TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD, and the authPolicy of the NV Index.
+If TPMA_NV_READLOCKED of the NV Index is SET, then the TPM shall return TPM_RC_NV_LOCKED.
+NOTE
+
+If authorization sessions are present, they are checked before the read -lock status of the NV Index
+is checked.
+
+If the size parameter plus the offset parameter adds to a value that is greater than the size of the NV
+Index data area, the TPM shall return TPM_RC_NV_RANGE and not read any data from the NV Index.
+If the NV Index has been defined but the TPMA_NV_WRITTEN attribute is CLEAR, then this command
+shall return TPM_RC_NV_UINITIALIZED even if size is zero.
+The data parameter in the response may be encrypted using parameter encryption.
+
+Page 432
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.13.2
+
+Part 3: Commands
+
+Command and Response
+Table 217 — TPM2_NV_Read Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Read
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+the handle indicating the source of the authorization
+value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to be read
+Auth Index: None
+
+UINT16
+
+size
+
+number of octets to read
+
+UINT16
+
+offset
+
+octet offset into the area
+This value shall be less than or equal to the size of the
+nvIndex data.
+
+Table 218 — TPM2_NV_Read Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+TPM2B_MAX_NV_BUFFER
+
+data
+
+Family “2.0”
+Level 00 Revision 00.99
+
+the data read
+
+Published
+Copyright © TCG 2006-2013
+
+Page 433
+October 31, 2013
+
+ Part 3: Commands
+
+33.13.3
+1
+2
+3
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_Read_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to read from the Index referenced by nvIndex
+
+TPM_RC_NV_LOCKED
+
+the Index referenced by nvIndex is read locked
+
+TPM_RC_NV_RANGE
+
+read range defined by size and offset is outside the range of the
+Index referenced by nvIndex
+
+TPM_RC_NV_UNINITIALIZED
+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
+33
+34
+35
+36
+37
+
+Meaning
+
+the Index referenced by nvIndex has not been initialized (written)
+
+TPM_RC
+TPM2_NV_Read(
+NV_Read_In
+NV_Read_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+NV_INDEX
+TPM_RC
+
+nvIndex;
+result;
+
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Common read access checks. NvReadAccessChecks() returns
+// TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
+// error may be returned at this point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// Too much data
+if((in->size + in->offset) > nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// Command Output
+// Set the return size
+out->data.t.size = in->size;
+// Perform the read
+NvGetIndexData(in->nvIndex, &nvIndex, in->offset, in->size, out->data.t.buffer);
+return TPM_RC_SUCCESS;
+}
+
+Page 434
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.14 TPM2_NV_ReadLock
+33.14.1
+
+General Description
+
+If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent further
+reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR).
+Proper authorizations are required for this command as determined by TPMA_NV_PPREAD,
+TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD, and the authPolicy of the NV Index.
+NOTE
+
+Only an entity that may read an Index is allowed to lock the NV Index for read.
+
+If the command is properly authorized and TPMA_NV_READ_STCLEAR of the NV Index is SET, then the
+TPM shall SET TPMA_NV_READLOCKED for the NV Index. If TPMA_NV_READ_STCLEAR of the NV
+Index is CLEAR, then the TPM shall return TPM_RC_NV_ATTRIBUTE. TPMA_NV_READLOCKED will
+be CLEAR by the next TPM2_Startup(TPM_SU_CLEAR).
+It is not an error to use this command for an Index that is already locked for reading.
+An Index that had not been written may be locked for reading.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 435
+October 31, 2013
+
+ Part 3: Commands
+
+33.14.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 219 — TPM2_NV_ReadLock Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_ReadLock
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+the handle indicating the source of the authorization
+value
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+the NV Index to be locked
+Auth Index: None
+
+Table 220 — TPM2_NV_ReadLock Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Page 436
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.14.3
+1
+2
+3
+
+Part 3: Commands
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_ReadLock_fp.h"
+#include "NV_spt_fp.h"
+Error Returns
+TPM_RC_ATTRIBUTES
+
+TPMA_NV_READ_STCLEAR is not SET so Index referenced by
+nvIndex may not be write locked
+
+TPM_RC_NV_AUTHORIZATION
+
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+Meaning
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to read from the Index referenced by nvIndex
+
+TPM_RC
+TPM2_NV_ReadLock(
+NV_ReadLock_In *in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Input Validation
+// Common read access checks. NvReadAccessChecks() returns
+// TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
+// error may be returned at this point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_NV_AUTHORIZATION)
+return TPM_RC_NV_AUTHORIZATION;
+// Index is already locked for write
+else if(result == TPM_RC_NV_LOCKED)
+return TPM_RC_SUCCESS;
+// If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue.
+// It is not an error to read lock an uninitialized Index.
+}
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked
+if(nvIndex.publicArea.attributes.TPMA_NV_READ_STCLEAR == CLEAR)
+return TPM_RC_ATTRIBUTES + RC_NV_ReadLock_nvIndex;
+// Internal Data Update
+// Set the READLOCK attribute
+nvIndex.publicArea.attributes.TPMA_NV_READLOCKED = SET;
+// Write NV info back
+NvWriteIndexInfo(in->nvIndex, &nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 437
+October 31, 2013
+
+ Part 3: Commands
+
+Trusted Platform Module Library
+
+33.15 TPM2_NV_ChangeAuth
+33.15.1
+
+General Description
+
+This command allows the authorization secret for an NV Index to be changed.
+If successful, the authorization secret (authValue) of the NV Index associated with nvIndex is changed.
+This command requires that a policy session be used for authorization of nvIndex so that the ADMIN role
+may be asserted and that commandCode in the policy session context shall be
+TPM_CC_NV_ChangeAuth. That is, the policy must contain a specific authorization for changing the
+authorization value of the referenced object.
+NOTE
+
+The reason for this restriction is to ensure that the admin istrative actions on nvIndex require explicit
+approval while other commands may use policy that is not command -dependent.
+
+The size of the newAuth value may be no larger than the size of authorization indicated when the NV
+Index was defined.
+Since the NV Index authorization is changed before the response HMAC is calculated, the newAuth value
+is used when generating the response HMAC key if required. See Part 4 ComputeResponseHMAC().
+
+Page 438
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.15.2
+
+Part 3: Commands
+
+Command and Response
+Table 221 — TPM2_NV_ChangeAuth Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_ChangeAuth {NV}
+
+TPMI_RH_NV_INDEX
+
+@nvIndex
+
+handle of the object
+Auth Index: 1
+Auth Role: ADMIN
+
+TPM2B_AUTH
+
+newAuth
+
+new authorization value
+
+Table 222 — TPM2_NV_ChangeAuth Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 439
+October 31, 2013
+
+ Part 3: Commands
+
+33.15.3
+1
+2
+
+Trusted Platform Module Library
+
+Detailed Actions
+
+#include "InternalRoutines.h"
+#include "NV_ChangeAuth_fp.h"
+Error Returns
+TPM_RC_SIZE
+
+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
+33
+34
+35
+
+Meaning
+newAuth size is larger than the digest size of the Name algorithm for
+the Index referenced by 'nvIndex
+
+TPM_RC
+TPM2_NV_ChangeAuth(
+NV_ChangeAuth_In
+
+*in
+
+// IN: input parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+
+result;
+nvIndex;
+
+// Input Validation
+// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
+// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS) return result;
+// Read index info from NV
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Remove any trailing zeros that might have been added by the caller
+// to obfuscate the size.
+MemoryRemoveTrailingZeros(&(in->newAuth));
+// Make sure that the authValue is no larger than the nameAlg of the Index
+if(in->newAuth.t.size > CryptGetHashDigestSize(nvIndex.publicArea.nameAlg))
+return TPM_RC_SIZE + RC_NV_ChangeAuth_newAuth;
+// Internal Data Update
+// Change auth
+nvIndex.authValue = in->newAuth;
+// Write index info back to NV
+NvWriteIndexInfo(in->nvIndex, &nvIndex);
+return TPM_RC_SUCCESS;
+}
+
+Page 440
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 3: Commands
+
+33.16 TPM2_NV_Certify
+33.16.1
+
+General Description
+
+The purpose of this command is to certify the contents of an NV Index or portion of an NV Index.
+If proper authorization for reading the NV Index is provided, the portion of the NV Index selected by size
+and offset are included in an attestation block and signed using the key indicated by signHandle. The
+attestation also includes size and offset so that the range of the data can be determined.
+NOTE
+
+See 20.1 for description of how the signing scheme is selected.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 441
+October 31, 2013
+
+ Part 3: Commands
+
+33.16.2
+
+Trusted Platform Module Library
+
+Command and Response
+Table 223 — TPM2_NV_Certify Command
+
+Type
+
+Name
+
+Description
+
+TPMI_ST_COMMAND_TAG
+
+tag
+
+UINT32
+
+commandSize
+
+TPM_CC
+
+commandCode
+
+TPM_CC_NV_Certify
+
+TPMI_DH_OBJECT+
+
+@signHandle
+
+handle of the key used to sign the attestation structure
+Auth Index: 1
+Auth Role: USER
+
+TPMI_RH_NV_AUTH
+
+@authHandle
+
+handle indicating the source of the authorization value
+for the NV Index
+Auth Index: 2
+Auth Role: USER
+
+TPMI_RH_NV_INDEX
+
+nvIndex
+
+Index for the area to be certified
+Auth Index: None
+
+TPM2B_DATA
+
+qualifyingData
+
+user-provided qualifying data
+
+TPMT_SIG_SCHEME+
+
+inScheme
+
+signing scheme to use if the scheme for signHandle is
+TPM_ALG_NULL
+
+UINT16
+
+size
+
+number of octets to certify
+
+UINT16
+
+offset
+
+octet offset into the area
+This value shall be less than or equal to the size of the
+nvIndex data.
+
+Table 224 — TPM2_NV_Certify Response
+Type
+
+Name
+
+Description
+
+TPM_ST
+
+tag
+
+see clause 8
+
+UINT32
+
+responseSize
+
+TPM_RC
+
+responseCode
+
+.
+
+TPM2B_ATTEST
+
+certifyInfo
+
+the structure that was signed
+
+TPMT_SIGNATURE
+
+signature
+
+the asymmetric signature over certifyInfo using the key
+referenced by signHandle
+
+Page 442
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+33.16.3
+1
+2
+3
+4
+
+Detailed Actions
+
+#include
+#include
+#include
+#include
+
+Part 3: Commands
+
+"InternalRoutines.h"
+"Attest_spt_fp.h"
+"NV_spt_fp.h"
+"NV_Certify_fp.h"
+
+Error Returns
+TPM_RC_NV_AUTHORIZATION
+
+the authorization was valid but the authorizing entity (authHandle) is
+not allowed to read from the Index referenced by nvIndex
+
+TPM_RC_KEY
+
+signHandle does not reference a signing key
+
+TPM_RC_NV_LOCKED
+
+Index referenced by nvIndex is locked for reading
+
+TPM_RC_NV_RANGE
+
+offset plus size extends outside of the data range of the Index
+referenced by nvIndex
+
+TPM_RC_NV_UNINITIALIZED
+
+Index referenced by nvIndex has not been written
+
+TPM_RC_SCHEME
+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
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+Meaning
+
+inScheme is not an allowed value for the key definition
+
+TPM_RC
+TPM2_NV_Certify(
+NV_Certify_In
+NV_Certify_Out
+
+*in,
+*out
+
+// IN: input parameter list
+// OUT: output parameter list
+
+)
+{
+TPM_RC
+NV_INDEX
+TPMS_ATTEST
+
+result;
+nvIndex;
+certifyInfo;
+
+// Attestation command may cause the orderlyState to be cleared due to
+// the reporting of clock info. If this is the case, check if NV is
+// available first
+if(gp.orderlyState != SHUTDOWN_NONE)
+{
+// The command needs NV update. Check if NV is available.
+// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
+// this point
+result = NvIsAvailable();
+if(result != TPM_RC_SUCCESS)
+return result;
+}
+// Input Validation
+// Get NV index info
+NvGetIndexInfo(in->nvIndex, &nvIndex);
+// Common access checks. A TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
+// error may be returned at this point
+result = NvReadAccessChecks(in->authHandle, in->nvIndex);
+if(result != TPM_RC_SUCCESS)
+return result;
+// See if the range to be certified is out of the bounds of the defined
+// Index
+if((in->size + in->offset) > nvIndex.publicArea.dataSize)
+return TPM_RC_NV_RANGE;
+// Command Output
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 443
+October 31, 2013
+
+ Part 3: Commands
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+
+Trusted Platform Module Library
+
+// Filling in attest information
+// Common fields
+// FillInAttestInfo can return TPM_RC_SCHEME or TPM_RC_KEY
+result = FillInAttestInfo(in->signHandle,
+&in->inScheme,
+&in->qualifyingData,
+&certifyInfo);
+if(result != TPM_RC_SUCCESS)
+{
+if(result == TPM_RC_KEY)
+return TPM_RC_KEY + RC_NV_Certify_signHandle;
+else
+return RcSafeAddToResult(result, RC_NV_Certify_inScheme);
+}
+// NV certify specific fields
+// Attestation type
+certifyInfo.type = TPM_ST_ATTEST_NV;
+// Get the name of the index
+certifyInfo.attested.nv.indexName.t.size =
+NvGetName(in->nvIndex, &certifyInfo.attested.nv.indexName.t.name);
+// Set the return size
+certifyInfo.attested.nv.nvContents.t.size = in->size;
+// Set the offset
+certifyInfo.attested.nv.offset = in->offset;
+// Perform the read
+NvGetIndexData(in->nvIndex, &nvIndex,
+in->offset, in->size,
+certifyInfo.attested.nv.nvContents.t.buffer);
+// Sign attestation structure. A NULL signature will be returned if
+// signHandle is TPM_RH_NULL. SignAttestInfo() may return TPM_RC_VALUE,
+// TPM_RC_SCHEME or TPM_RC_ATTRUBUTES.
+// Note: SignAttestInfo may return TPM_RC_ATTRIBUTES if the key is not a
+// signing key but that was checked above. TPM_RC_VALUE would mean that the
+// data to sign is too large but the data to sign is a digest
+result = SignAttestInfo(in->signHandle,
+&in->inScheme,
+&certifyInfo,
+&in->qualifyingData,
+&out->certifyInfo,
+&out->signature);
+if(result != TPM_RC_SUCCESS)
+return result;
+// orderly state should be cleared because of the reporting of clock info
+// if signing happens
+if(in->signHandle != TPM_RH_NULL)
+g_clearOrderly = TRUE;
+return TPM_RC_SUCCESS;
+}
+
+Page 444
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+
diff --git a/trunks/generator/raw_structures.txt b/trunks/generator/raw_structures.txt
new file mode 100644
index 0000000..6d375fe
--- /dev/null
+++ b/trunks/generator/raw_structures.txt
@@ -0,0 +1,17797 @@
+Trusted Platform Module Library
+Part 2: Structures
+Family “2.0”
+Level 00 Revision 00.99
+October 31, 2013
+
+Contact: admin@trustedcomputinggroup.org
+
+Published
+Copyright © TCG 2006-2013
+
+TCG
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Licenses and Notices
+1. Copyright Licenses:
+
+
+Trusted Computing Group (TCG) grants to the user of the source code in this specification (the
+“Source Code”) a worldwide, irrevocable, nonexclusive, royalty free, copyright license to
+reproduce, create derivative works, distribute, display and perform the Source Code and
+derivative works thereof, and to grant others the rights granted herein.
+
+
+
+The TCG grants to the user of the other parts of the specification (other than the Source Code)
+the rights to reproduce, distribute, display, and perform the specification solely for the purpose of
+developing products based on such documents.
+
+2. Source Code Distribution Conditions:
+
+
+Redistributions of Source Code must retain the above copyright licenses, this list of conditions
+and the following disclaimers.
+
+
+
+Redistributions in binary form must reproduce the above copyright licenses, this list of conditions
+and the following disclaimers in the documentation and/or other materials provided with the
+distribution.
+
+3. Disclaimers:
+
+
+THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF
+LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH
+RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)
+THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.
+Contact TCG Administration (admin@trustedcomputinggroup.org) for information on specification
+licensing rights available through TCG membership agreements.
+
+
+
+THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES
+WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF
+INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF
+ANY PROPOSAL, SPECIFICATION OR SAMPLE.
+
+
+
+Without limitation, TCG and its members and licensors disclaim all liability, including liability for
+infringement of any proprietary rights, relating to use of information in this specification and to the
+implementation of this specification, and TCG disclaims all liability for cost of procurement of
+substitute goods or services, lost profits, loss of use, loss of data or any incidental, consequential,
+direct, indirect, or special damages, whether under contract, tort, warranty or otherwise, arising in
+any way out of use or reliance upon this specification or any information herein.
+
+Any marks and brands contained herein are the property of their respective owners.
+
+Page ii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+CONTENTS
+1
+
+Scope .................................................................................................................................................... 1
+
+2
+
+Terms and definitions ............................................................................................................................ 1
+
+3
+
+Symbols and abbreviated terms ............................................................................................................ 1
+
+4
+
+Notation ................................................................................................................................................. 1
+4.1
+Introduction ................................................................................................................................ 1
+4.2
+Named Constants ...................................................................................................................... 2
+4.3
+Data Type Aliases (typedefs) .................................................................................................... 3
+4.4
+Enumerations............................................................................................................................. 3
+4.5
+Interface Type ............................................................................................................................ 4
+4.6
+Arrays ........................................................................................................................................ 5
+4.7
+Structure Definitions .................................................................................................................. 6
+4.8
+Conditional Types ...................................................................................................................... 7
+4.9
+Unions........................................................................................................................................ 8
+4.9.1
+Introduction...................................................................................................................... 8
+4.9.2
+Union Definition ............................................................................................................... 8
+4.9.3
+Union Instance ................................................................................................................ 9
+4.9.4
+Union Selector Definition ............................................................................................... 10
+4.10 Bit Field Definitions .................................................................................................................. 11
+4.11 Parameter Limits ..................................................................................................................... 11
+4.12 Enumeration Macro ................................................................................................................. 13
+4.13 Size Checking .......................................................................................................................... 13
+4.14 Data Direction .......................................................................................................................... 14
+4.15 Structure Validations ............................................................................................................... 14
+4.16 Name Prefix Convention .......................................................................................................... 14
+4.17 Data Alignment ........................................................................................................................ 15
+4.18 Parameter Unmarshaling Errors .............................................................................................. 15
+
+5
+
+Base Types ......................................................................................................................................... 17
+5.1
+Primitive Types ........................................................................................................................ 17
+5.2
+Miscellaneous Types ............................................................................................................... 17
+
+6
+
+Constants ............................................................................................................................................ 18
+6.1
+TPM_SPEC (Specification Version Values) ............................................................................ 18
+6.2
+TPM_GENERATED ................................................................................................................. 18
+6.3
+TPM_ALG_ID .......................................................................................................................... 19
+6.4
+TPM_ECC_CURVE ................................................................................................................. 22
+6.5
+TPM_CC (Command Codes) .................................................................................................. 22
+6.5.1
+Format ........................................................................................................................... 22
+6.5.2
+Description .................................................................................................................... 23
+6.5.3
+TPM_CC Listing ............................................................................................................ 24
+6.6
+TPM_RC (Response Codes) ................................................................................................... 28
+6.6.1
+Description .................................................................................................................... 28
+6.6.2
+Response Code Formats .............................................................................................. 29
+6.6.3
+TPM_RC Values ........................................................................................................... 32
+6.7
+TPM_CLOCK_ADJUST ........................................................................................................... 37
+6.8
+TPM_EO (EA Arithmetic Operands) ........................................................................................ 37
+6.9
+TPM_ST (Structure Tags) ....................................................................................................... 38
+6.10 TPM_SU (Startup Type) .......................................................................................................... 40
+6.11 TPM_SE (Session Type) ......................................................................................................... 40
+6.12 TPM_CAP (Capabilities) .......................................................................................................... 41
+6.13 TPM_PT (Property Tag) .......................................................................................................... 41
+6.14 TPM_PT_PCR (PCR Property Tag) ........................................................................................ 47
+6.15 TPM_PS (Platform Specific) .................................................................................................... 49
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page iii
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+7
+
+Handles ............................................................................................................................................... 50
+7.1
+Introduction .............................................................................................................................. 50
+7.2
+TPM_HT (Handle Types) ......................................................................................................... 50
+7.3
+Persistent Handle Sub-ranges................................................................................................. 51
+7.4
+TPM_RH (Permanent Handles)............................................................................................... 52
+7.5
+TPM_HC (Handle Value Constants) ....................................................................................... 53
+
+8
+
+Attribute Structures .............................................................................................................................. 55
+8.1
+Description ............................................................................................................................... 55
+8.2
+TPMA_ALGORITHM ............................................................................................................... 55
+8.3
+TPMA_OBJECT (Object Attributes) ........................................................................................ 55
+8.3.1
+Introduction.................................................................................................................... 55
+8.3.2
+Structure Definition ........................................................................................................ 56
+8.3.3
+Attribute Descriptions .................................................................................................... 57
+8.3.3.1
+Introduction ............................................................................................................ 57
+8.3.3.2
+Bit[1] – fixedTPM ................................................................................................... 57
+8.3.3.3
+Bit[2] – stClear ....................................................................................................... 58
+8.3.3.4
+Bit[4] – fixedParent ................................................................................................ 58
+8.3.3.5
+Bit[5] – sensitiveDataOrigin ................................................................................... 58
+8.3.3.6
+Bit[6] – userWithAuth............................................................................................. 59
+8.3.3.7
+Bit[7] – adminWithPolicy........................................................................................ 59
+8.3.3.8
+Bit[10] – noDA ....................................................................................................... 59
+8.3.3.9
+Bit[11] – encryptedDuplication .............................................................................. 60
+8.3.3.10
+Bit[16] – restricted ................................................................................................. 60
+8.3.3.11
+Bit[17] – decrypt .................................................................................................... 61
+8.3.3.12
+Bit[18] – sign .......................................................................................................... 61
+8.4
+TPMA_SESSION (Session Attributes) .................................................................................... 62
+8.5
+TPMA_LOCALITY (Locality Attribute) ..................................................................................... 63
+8.6
+TPMA_PERMANENT .............................................................................................................. 64
+8.7
+TPMA_STARTUP_CLEAR ...................................................................................................... 65
+8.8
+TPMA_MEMORY .................................................................................................................... 66
+8.9
+TPMA_CC (Command Code Attributes) ................................................................................. 67
+8.9.1
+Introduction.................................................................................................................... 67
+8.9.2
+Structure Definition ........................................................................................................ 67
+8.9.3
+Field Descriptions .......................................................................................................... 67
+8.9.3.1
+Bits[15:0] – commandIndex ................................................................................... 67
+8.9.3.2
+Bit[22] – nv ............................................................................................................ 67
+8.9.3.3
+Bit[23] – extensive ................................................................................................. 67
+8.9.3.4
+Bit[24] – flushed ..................................................................................................... 68
+8.9.3.5
+Bits[27:25] – cHandles .......................................................................................... 68
+8.9.3.6
+Bit[28] – rHandle .................................................................................................... 68
+8.9.3.7
+Bit[29] – V .............................................................................................................. 69
+8.9.3.8
+Bits[31:30] – Res ................................................................................................... 69
+
+9
+
+Interface Types .................................................................................................................................... 70
+9.1
+Introduction .............................................................................................................................. 70
+9.2
+TPMI_YES_NO ....................................................................................................................... 70
+9.3
+TPMI_DH_OBJECT ................................................................................................................. 70
+9.4
+TPMI_DH_PERSISTENT ........................................................................................................ 71
+9.5
+TPMI_DH_ENTITY .................................................................................................................. 71
+9.6
+TPMI_DH_PCR ....................................................................................................................... 72
+9.7
+TPMI_SH_AUTH_SESSION ................................................................................................... 72
+9.8
+TPMI_SH_HMAC .................................................................................................................... 72
+9.9
+TPMI_SH_POLICY .................................................................................................................. 72
+9.10 TPMI_DH_CONTEXT .............................................................................................................. 73
+9.11 TPMI_RH_HIERARCHY .......................................................................................................... 73
+9.12 TPMI_RH_ENABLES .............................................................................................................. 73
+
+Page iv
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+9.13
+9.14
+9.15
+9.16
+9.17
+9.18
+9.19
+9.20
+9.21
+9.22
+9.23
+9.24
+9.25
+9.26
+9.27
+9.28
+9.29
+9.30
+10
+
+Part 2: Structures
+
+TPMI_RH_HIERARCHY_AUTH .............................................................................................. 74
+TPMI_RH_PLATFORM ........................................................................................................... 74
+TPMI_RH_OWNER ................................................................................................................. 74
+TPMI_RH_ENDORSEMENT ................................................................................................... 75
+TPMI_RH_PROVISION ........................................................................................................... 75
+TPMI_RH_CLEAR ................................................................................................................... 75
+TPMI_RH_NV_AUTH .............................................................................................................. 76
+TPMI_RH_LOCKOUT ............................................................................................................. 76
+TPMI_RH_NV_INDEX ............................................................................................................. 76
+TPMI_ALG_HASH ................................................................................................................... 77
+TPMI_ALG_ASYM (Asymmetric Algorithms) .......................................................................... 77
+TPMI_ALG_SYM (Symmetric Algorithms) .............................................................................. 78
+TPMI_ALG_SYM_OBJECT ..................................................................................................... 78
+TPMI_ALG_SYM_MODE ........................................................................................................ 79
+TPMI_ALG_KDF (Key and Mask Generation Functions) ........................................................ 79
+TPMI_ALG_SIG_SCHEME ..................................................................................................... 80
+TPMI_ECC_KEY_EXCHANGE ............................................................................................... 80
+TPMI_ST_COMMAND_TAG ................................................................................................... 80
+
+Structure Definitions ............................................................................................................................ 81
+10.1 TPMS_ALGORITHM_DESCRIPTION .................................................................................... 81
+10.2 Hash/Digest Structures ............................................................................................................ 81
+10.2.1
+TPMU_HA (Hash) ......................................................................................................... 81
+10.2.2
+TPMT_HA...................................................................................................................... 82
+10.3 Sized Buffers ........................................................................................................................... 82
+10.3.1
+Introduction.................................................................................................................... 82
+10.3.2
+TPM2B_DIGEST ........................................................................................................... 83
+10.3.3
+TPM2B_DATA ............................................................................................................... 83
+10.3.4
+TPM2B_NONCE ........................................................................................................... 83
+10.3.5
+TPM2B_AUTH .............................................................................................................. 83
+10.3.6
+TPM2B_OPERAND ...................................................................................................... 84
+10.3.7
+TPM2B_EVENT ............................................................................................................ 84
+10.3.8
+TPM2B_MAX_BUFFER ................................................................................................ 84
+10.3.9
+TPM2B_MAX_NV_BUFFER ......................................................................................... 84
+10.3.10 TPM2B_TIMEOUT ........................................................................................................ 85
+10.3.11 TPM2B_IV ..................................................................................................................... 85
+10.4 Names ..................................................................................................................................... 85
+10.4.1
+Introduction.................................................................................................................... 85
+10.4.2
+TPMU_NAME ................................................................................................................ 85
+10.4.3
+TPM2B_NAME .............................................................................................................. 86
+10.5 PCR Structures ........................................................................................................................ 86
+10.5.1
+TPMS_PCR_SELECT ................................................................................................... 86
+10.5.2
+TPMS_PCR_SELECTION ............................................................................................ 87
+10.6 Tickets ..................................................................................................................................... 87
+10.6.1
+Introduction.................................................................................................................... 87
+10.6.2
+A NULL Ticket ............................................................................................................... 88
+10.6.3
+TPMT_TK_CREATION ................................................................................................. 89
+10.6.4
+TPMT_TK_VERIFIED ................................................................................................... 90
+10.6.5
+TPMT_TK_AUTH .......................................................................................................... 91
+10.6.6
+TPMT_TK_HASHCHECK ............................................................................................. 92
+10.7 Property Structures .................................................................................................................. 92
+10.7.1
+TPMS_ALG_PROPERTY ............................................................................................. 92
+10.7.2
+TPMS_TAGGED_PROPERTY ..................................................................................... 92
+10.7.3
+TPMS_TAGGED_PCR_SELECT ................................................................................. 93
+10.8 Lists ......................................................................................................................................... 93
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page v
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.8.1
+TPML_CC...................................................................................................................... 93
+10.8.2
+TPML_CCA ................................................................................................................... 94
+10.8.3
+TPML_ALG.................................................................................................................... 94
+10.8.4
+TPML_HANDLE ............................................................................................................ 94
+10.8.5
+TPML_DIGEST ............................................................................................................. 95
+10.8.6
+TPML_DIGEST_VALUES ............................................................................................. 95
+10.8.7
+TPM2B_DIGEST_VALUES........................................................................................... 95
+10.8.8
+TPML_PCR_SELECTION............................................................................................. 96
+10.8.9
+TPML_ALG_PROPERTY.............................................................................................. 96
+10.8.10 TPML_TAGGED_TPM_PROPERTY ............................................................................ 96
+10.8.11 TPML_TAGGED_PCR_PROPERTY ............................................................................ 97
+10.8.12 TPML_ECC_CURVE .................................................................................................... 97
+10.9 Capabilities Structures ............................................................................................................. 97
+10.9.1
+TPMU_CAPABILITIES .................................................................................................. 97
+10.9.2
+TPMS_CAPABILITY_DATA .......................................................................................... 98
+10.10 Clock/Counter Structures ........................................................................................................ 98
+10.10.1 TPMS_CLOCK_INFO ................................................................................................... 98
+10.10.2 Clock ............................................................................................................................. 98
+10.10.3 ResetCount ................................................................................................................... 98
+10.10.4 RestartCount ................................................................................................................. 99
+10.10.5 Safe ............................................................................................................................... 99
+10.10.6 TPMS_TIME_INFO ....................................................................................................... 99
+10.11 TPM Attestation Structures .................................................................................................... 100
+10.11.1 Introduction.................................................................................................................. 100
+10.11.2 TPMS_TIME_ATTEST_INFO ..................................................................................... 100
+10.11.3 TPMS_CERTIFY_INFO .............................................................................................. 100
+10.11.1 TPMS_QUOTE_INFO ................................................................................................. 100
+10.11.2 TPMS_COMMAND_AUDIT_INFO .............................................................................. 101
+10.11.3 TPMS_SESSION_AUDIT_INFO ................................................................................. 101
+10.11.4 TPMS_CREATION_INFO ........................................................................................... 101
+10.11.5 TPMS_NV_CERTIFY_INFO ....................................................................................... 101
+10.11.6 TPMI_ST_ATTEST ..................................................................................................... 102
+10.11.7 TPMU_ATTEST .......................................................................................................... 102
+10.11.8 TPMS_ATTEST .......................................................................................................... 103
+10.11.9 TPM2B_ATTEST ........................................................................................................ 103
+10.12 Authorization Structures ........................................................................................................ 104
+10.12.1 TPMS_AUTH_COMMAND ......................................................................................... 104
+10.12.2 TPMS_AUTH_RESPONSE ........................................................................................ 104
+11
+
+Algorithm Parameters and Structures ............................................................................................... 105
+11.1 Symmetric .............................................................................................................................. 105
+11.1.1
+Introduction.................................................................................................................. 105
+11.1.2
+TPMI_AES_KEY_BITS ............................................................................................... 105
+11.1.3
+TPMI_SM4_KEY_BITS ............................................................................................... 105
+11.1.4
+TPMU_SYM_KEY_BITS ............................................................................................. 106
+11.1.5
+TPMU_SYM_MODE ................................................................................................... 106
+11.1.6
+TPMU_SYM_DETAILS ............................................................................................... 107
+11.1.7
+TPMT_SYM_DEF ....................................................................................................... 107
+11.1.8
+TPMT_SYM_DEF_OBJECT ....................................................................................... 107
+11.1.9
+TPM2B_SYM_KEY ..................................................................................................... 108
+11.1.10 TPMS_SYMCIPHER_PARMS .................................................................................... 108
+11.1.11 TPM2B_SENSITIVE_DATA ........................................................................................ 108
+11.1.12 TPMS_SENSITIVE_CREATE ..................................................................................... 109
+11.1.13 TPM2B_SENSITIVE_CREATE ................................................................................... 110
+11.1.14 TPMS_SCHEME_SIGHASH....................................................................................... 110
+11.1.15 TPMI_ALG_HASH_SCHEME ..................................................................................... 110
+
+Page vi
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.16 HMAC_SIG_SCHEME ................................................................................................ 110
+11.1.17 TPMS_SCHEME_XOR ............................................................................................... 111
+11.1.18 TPMU_SCHEME_HMAC ............................................................................................ 111
+11.1.19 TPMT_KEYEDHASH_SCHEME ................................................................................. 111
+11.2 Asymmetric ............................................................................................................................ 112
+11.2.1
+Signing Schemes ........................................................................................................ 112
+11.2.1.1
+Introduction .......................................................................................................... 112
+11.2.1.2
+RSA_SIG_SCHEMES ......................................................................................... 112
+11.2.1.3
+ECC_SIG_SCHEMES ......................................................................................... 112
+11.2.1.4
+TPMS_SCHEME_ECDAA................................................................................... 112
+11.2.1.5
+TPMU_SIG_SCHEME......................................................................................... 113
+11.2.1.6
+TPMT_SIG_SCHEME ......................................................................................... 113
+11.2.2
+Encryption Schemes ................................................................................................... 114
+11.2.2.1
+Introduction .......................................................................................................... 114
+11.2.2.2
+TPMS_SCHEME_OAEP ..................................................................................... 114
+11.2.2.3
+TPMS_SCHEME_ECDH ..................................................................................... 114
+11.2.3
+Key Derivation Schemes ............................................................................................. 114
+11.2.3.1
+Introduction .......................................................................................................... 114
+11.2.3.2
+TPMS_SCHEME_MGF1 ..................................................................................... 114
+11.2.3.3
+TPMS_SCHEME_KDF1_SP800_56a ................................................................. 114
+11.2.3.4
+TPMS_SCHEME_KDF2 ...................................................................................... 115
+11.2.3.5
+TPMS_SCHEME_KDF1_SP800_108 ................................................................. 115
+11.2.3.6
+TPMU_KDF_SCHEME........................................................................................ 115
+11.2.3.7
+TPMT_KDF_SCHEME ........................................................................................ 115
+11.2.3.8
+TPMI_ALG_ASYM_SCHEME ............................................................................. 116
+11.2.3.9
+TPMU_ASYM_SCHEME..................................................................................... 116
+11.2.3.10 TPMT_ASYM_SCHEME ..................................................................................... 117
+11.2.4
+RSA ............................................................................................................................. 117
+11.2.4.1
+TPMI_ALG_RSA_SCHEME ................................................................................ 117
+11.2.4.2
+TPMT_RSA_SCHEME ........................................................................................ 117
+11.2.4.3
+TPMI_ALG_RSA_DECRYPT .............................................................................. 118
+11.2.4.4
+TPMT_RSA_DECRYPT ...................................................................................... 118
+11.2.4.5
+TPM2B_PUBLIC_KEY_RSA ............................................................................... 118
+11.2.4.6
+TPMI_RSA_KEY_BITS ....................................................................................... 118
+11.2.4.7
+TPM2B_PRIVATE_KEY_RSA ............................................................................ 119
+11.2.5
+ECC ............................................................................................................................. 120
+11.2.5.1
+TPM2B_ECC_PARAMETER .............................................................................. 120
+11.2.5.2
+TPMS_ECC_POINT ............................................................................................ 120
+11.2.5.3
+TPM2B_ECC_POINT .......................................................................................... 120
+11.2.5.4
+TPMI_ALG_ECC_SCHEME ............................................................................... 121
+11.2.5.5
+TPMI_ECC_CURVE ............................................................................................ 121
+11.2.5.6
+TPMT_ECC_SCHEME........................................................................................ 121
+11.2.5.7
+TPMS_ALGORITHM_DETAIL_ECC ................................................................... 122
+11.3 Signatures.............................................................................................................................. 122
+11.3.1
+TPMS_SIGNATURE_RSASSA .................................................................................. 122
+11.3.2
+TPMS_SIGNATURE_RSAPSS .................................................................................. 122
+11.3.3
+TPMS_SIGNATURE_ECDSA ..................................................................................... 123
+11.3.4
+TPMU_SIGNATURE ................................................................................................... 123
+11.3.5
+TPMT_SIGNATURE ................................................................................................... 124
+11.4 Key/Secret Exchange ............................................................................................................ 124
+11.4.1
+Introduction.................................................................................................................. 124
+11.4.2
+TPMU_ENCRYPTED_SECRET ................................................................................. 124
+11.4.3
+TPM2B_ENCRYPTED_SECRET ............................................................................... 125
+12
+
+Key/Object Complex.......................................................................................................................... 126
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page vii
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+12.1 Introduction ............................................................................................................................ 126
+12.2 Public Area Structures ........................................................................................................... 126
+12.2.1
+Description .................................................................................................................. 126
+12.2.2
+TPMI_ALG_PUBLIC ................................................................................................... 126
+12.2.3
+Type-Specific Parameters ........................................................................................... 126
+12.2.3.1
+Description .......................................................................................................... 126
+12.2.3.2
+TPMU_PUBLIC_ID .............................................................................................. 127
+12.2.3.3
+TPMS_KEYEDHASH_PARMS ........................................................................... 127
+12.2.3.4
+TPMS_ASYM_PARMS ....................................................................................... 127
+12.2.3.5
+TPMS_RSA_PARMS .......................................................................................... 128
+12.2.3.6
+TPMS_ECC_PARMS .......................................................................................... 129
+12.2.3.7
+TPMU_PUBLIC_PARMS .................................................................................... 129
+12.2.3.8
+TPMT_PUBLIC_PARMS ..................................................................................... 130
+12.2.4
+TPMT_PUBLIC ........................................................................................................... 130
+12.2.5
+TPM2B_PUBLIC ......................................................................................................... 131
+12.3 Private Area Structures ......................................................................................................... 131
+12.3.1
+Introduction.................................................................................................................. 131
+12.3.2
+Sensitive Data Structures ............................................................................................ 131
+12.3.2.1
+Introduction .......................................................................................................... 131
+12.3.2.2
+TPM2B_PRIVATE_VENDOR_SPECIFIC ........................................................... 131
+12.3.2.3
+TPMU_SENSITIVE_COMPOSITE ...................................................................... 132
+12.3.2.4
+TPMT_SENSITIVE .............................................................................................. 132
+12.3.3
+TPM2B_SENSITIVE ................................................................................................... 132
+12.3.4
+Encryption ................................................................................................................... 133
+12.3.5
+Integrity........................................................................................................................ 133
+12.3.6
+_PRIVATE ................................................................................................................... 133
+12.3.7
+TPM2B_PRIVATE ....................................................................................................... 133
+12.4 Identity Object ........................................................................................................................ 134
+12.4.1
+Description .................................................................................................................. 134
+12.4.2
+_ID_OBJECT .............................................................................................................. 134
+12.4.3
+TPM2B_ID_OBJECT .................................................................................................. 134
+13
+
+NV Storage Structures ...................................................................................................................... 135
+13.1 TPM_NV_INDEX ................................................................................................................... 135
+13.2 TPMA_NV (NV Index Attributes) ........................................................................................... 136
+13.3 TPMS_NV_PUBLIC ............................................................................................................... 139
+13.4 TPM2B_NV_PUBLIC ............................................................................................................. 139
+
+14
+
+Context Data ..................................................................................................................................... 140
+14.1 Introduction ............................................................................................................................ 140
+14.2 TPM2B_CONTEXT_SENSITIVE........................................................................................... 140
+14.3 TPMS_CONTEXT_DATA ...................................................................................................... 140
+14.4 TPM2B_CONTEXT_DATA .................................................................................................... 140
+14.5 TPMS_CONTEXT ................................................................................................................. 141
+14.6 Parameters of TPMS_CONTEXT .......................................................................................... 142
+14.6.1
+sequence ..................................................................................................................... 142
+14.6.2
+savedHandle ............................................................................................................... 142
+14.6.3
+hierarchy...................................................................................................................... 143
+14.7 Context Protection ................................................................................................................. 143
+14.7.1
+Context Integrity .......................................................................................................... 143
+14.7.2
+Context Confidentiality ................................................................................................ 143
+
+15
+
+Creation Data .................................................................................................................................... 144
+15.1 TPMS_CREATION_DATA .................................................................................................... 144
+15.2 TPM2B_CREATION_DATA .................................................................................................. 144
+
+Page viii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Annex A (informative) Algorithm Constants ............................................................................................. 145
+A.1
+Introduction ............................................................................................................................ 145
+A.2
+Allowed Hash Algorithms....................................................................................................... 145
+A.2.1
+SHA1 ........................................................................................................................... 145
+A.2.2
+SHA256 ....................................................................................................................... 145
+A.2.3
+SHA384 ....................................................................................................................... 145
+A.2.4
+SHA512 ....................................................................................................................... 146
+A.2.5
+SM3_256 ..................................................................................................................... 146
+A.3
+Architectural Limits ................................................................................................................ 146
+Annex B (informative) Implementation Definitions ................................................................................... 147
+B.1
+Introduction ............................................................................................................................ 147
+B.2
+Logic Values .......................................................................................................................... 147
+B.3
+Processor Values .................................................................................................................. 147
+B.4
+Implemented Algorithms ........................................................................................................ 148
+B.5
+Implemented Commands ...................................................................................................... 148
+B.6
+Algorithm Constants .............................................................................................................. 151
+B.6.1
+RSA ............................................................................................................................. 152
+B.6.2
+ECC ............................................................................................................................. 152
+B.6.3
+AES ............................................................................................................................. 152
+B.6.4
+SM4 ............................................................................................................................. 152
+B.6.5
+Symmetric ................................................................................................................... 153
+B.7
+Implementation Specific Values ............................................................................................ 154
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page ix
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Tables
+Table 1 — Name Prefix Convention ........................................................................................................... 15
+Table 2 — Unmarshaling Errors ................................................................................................................. 16
+Table 3 — Definition of Base Types ........................................................................................................... 17
+Table 4 — Definition of Types for Documentation Clarity ........................................................................... 17
+Table 5 — Definition of (UINT32) TPM_SPEC Constants <> ..................................................................... 18
+Table 6 — Definition of (UINT32) TPM_GENERATED Constants <O> ..................................................... 18
+Table 7 — Definition of (UINT16) TPM_ALG_ID Constants <IN/OUT, S> ................................................. 19
+Table 8 — Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants <IN/OUT, S> ............................ 22
+Table 9 — TPM Command Format Fields Description ............................................................................... 22
+Table 10 — Legend for Command Code Tables ........................................................................................ 23
+Table 11 — Definition of (UINT32) TPM_CC Constants (Numeric Order) <IN/OUT, S> ........................... 24
+Table 12 — Format-Zero Response Codes ................................................................................................ 30
+Table 13 — Format-One Response Codes ................................................................................................ 31
+Table 14 — Response Code Groupings ..................................................................................................... 31
+Table 15 — Definition of (UINT32) TPM_RC Constants (Actions) <OUT> ................................................ 32
+Table 16 — Definition of (INT8) TPM_CLOCK_ADJUST Constants <IN> ................................................. 37
+Table 17 — Definition of (UINT16) TPM_EO Constants <IN/OUT> ........................................................... 37
+Table 18 — Definition of (UINT16) TPM_ST Constants <IN/OUT, S> ....................................................... 38
+Table 19 — Definition of (UINT16) TPM_SU Constants <IN> .................................................................... 40
+Table 20 — Definition of (UINT8) TPM_SE Constants <IN> ...................................................................... 40
+Table 21 — Definition of (UINT32) TPM_CAP Constants .......................................................................... 41
+Table 22 — Definition of (UINT32) TPM_PT Constants <IN/OUT, S> ....................................................... 41
+Table 23 — Definition of (UINT32) TPM_PT_PCR Constants <IN/OUT, S> ............................................. 47
+Table 24 — Definition of (UINT32) TPM_PS Constants <OUT> ................................................................ 49
+Table 25 — Definition of Types for Handles ............................................................................................... 50
+Table 26 — Definition of (UINT8) TPM_HT Constants <S> ....................................................................... 50
+Table 27 — Definition of (UINT32) TPM_RH Constants <IN, S> ............................................................... 52
+Table 28 — Definition of (TPM_HANDLE) TPM_HC Constants <IN, S> ................................................... 54
+Table 29 — Definition of (UINT32) TPMA_ALGORITHM Bits .................................................................... 55
+Table 30 — Definition of (UINT32) TPMA_OBJECT Bits ........................................................................... 56
+Table 31 — Definition of (UINT8) TPMA_SESSION Bits <IN/OUT> .......................................................... 62
+Table 32 — Definition of (UINT8) TPMA_LOCALITY Bits <IN/OUT> ........................................................ 64
+Table 33 — Definition of (UINT32) TPMA_PERMANENT Bits <OUT> ...................................................... 64
+Table 34 — Definition of (UINT32) TPMA_STARTUP_CLEAR Bits <OUT> .............................................. 65
+Table 35 — Definition of (UINT32) TPMA_MEMORY Bits <Out> .............................................................. 66
+Table 36 — Definition of (TPM_CC) TPMA_CC Bits <OUT> ..................................................................... 67
+Table 37 — Definition of (BYTE) TPMI_YES_NO Type ............................................................................. 70
+
+Page x
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 38 — Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type........................................................ 70
+Table 39 — Definition of (TPM_HANDLE) TPMI_DH_PERSISTENT Type ............................................... 71
+Table 40 — Definition of (TPM_HANDLE) TPMI_DH_ENTITY Type <IN> ................................................ 71
+Table 41 — Definition of (TPM_HANDLE) TPMI_DH_PCR Type <IN> ..................................................... 72
+Table 42 — Definition of (TPM_HANDLE) TPMI_SH_AUTH_SESSION Type <IN/OUT> ........................ 72
+Table 43 — Definition of (TPM_HANDLE) TPMI_SH_HMAC Type <IN/OUT> .......................................... 72
+Table 44 — Definition of (TPM_HANDLE) TPMI_SH_POLICY Type <IN/OUT> ....................................... 72
+Table 45 — Definition of (TPM_HANDLE) TPMI_DH_CONTEXT Type .................................................... 73
+Table 46 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY Type ................................................ 73
+Table 47 — Definition of (TPM_HANDLE) TPMI_RH_ENABLES Type ..................................................... 73
+Table 48 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_AUTH Type <IN> ............................ 74
+Table 49 — Definition of (TPM_HANDLE) TPMI_RH_PLATFORM Type <IN> ......................................... 74
+Table 50 — Definition of (TPM_HANDLE) TPMI_RH_OWNER Type <IN> ............................................... 74
+Table 51 — Definition of (TPM_HANDLE) TPMI_RH_ENDORSEMENT Type <IN> ................................. 75
+Table 52 — Definition of (TPM_HANDLE) TPMI_RH_PROVISION Type <IN> ......................................... 75
+Table 53 — Definition of (TPM_HANDLE) TPMI_RH_CLEAR Type <IN> ................................................. 75
+Table 54 — Definition of (TPM_HANDLE) TPMI_RH_NV_AUTH Type <IN> ............................................ 76
+Table 55 — Definition of (TPM_HANDLE) TPMI_RH_LOCKOUT Type <IN> ........................................... 76
+Table 56 — Definition of (TPM_HANDLE) TPMI_RH_NV_INDEX Type <IN/OUT> .................................. 76
+Table 57 — Definition of (TPM_ALG_ID) TPMI_ALG_HASH Type............................................................ 77
+Table 58 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM Type ........................................................... 77
+Table 59 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM Type .............................................................. 78
+Table 60 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_OBJECT Type ............................................. 78
+Table 61 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_MODE Type ................................................. 79
+Table 62 — Definition of (TPM_ALG_ID) TPMI_ALG_KDF Type .............................................................. 79
+Table 63 — Definition of (TPM_ALG_ID) TPMI_ALG_SIG_SCHEME Type .............................................. 80
+Table 64 — Definition of (TPM_ALG_ID) TPMI_ECC_KEY_EXCHANGE Type ........................................ 80
+Table 65 — Definition of (TPM_ST) TPMI_ST_COMMAND_TAG Type .................................................... 80
+Table 66 — Definition of TPMS_ALGORITHM_DESCRIPTION Structure <OUT> .................................... 81
+Table 67 — Definition of TPMU_HA Union <IN/OUT, S> ........................................................................... 81
+Table 68 — Definition of TPMT_HA Structure <IN/OUT> .......................................................................... 82
+Table 69 — Definition of TPM2B_DIGEST Structure ................................................................................. 83
+Table 70 — Definition of TPM2B_DATA Structure ..................................................................................... 83
+Table 71 — Definition of Types for TPM2B_NONCE ................................................................................. 83
+Table 72 — Definition of Types for TPM2B_AUTH .................................................................................... 83
+Table 73 — Definition of Types for TPM2B_OPERAND ............................................................................ 84
+Table 74 — Definition of TPM2B_EVENT Structure ................................................................................... 84
+Table 75 — Definition of TPM2B_MAX_BUFFER Structure ...................................................................... 84
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xi
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Table 76 — Definition of TPM2B_MAX_NV_BUFFER Structure ............................................................... 84
+Table 77 — Definition of TPM2B_TIMEOUT Structure <IN/OUT> ............................................................. 85
+Table 78 — Definition of TPM2B_IV Structure <IN/OUT> .......................................................................... 85
+Table 79 — Definition of TPMU_NAME Union <> ...................................................................................... 85
+Table 80 — Definition of TPM2B_NAME Structure .................................................................................... 86
+Table 81 — Definition of TPMS_PCR_SELECT Structure ......................................................................... 87
+Table 82 — Definition of TPMS_PCR_SELECTION Structure ................................................................... 87
+Table 83 — Values for proof Used in Tickets ............................................................................................. 88
+Table 84 — General Format of a Ticket ...................................................................................................... 88
+Table 85 — Definition of TPMT_TK_CREATION Structure ........................................................................ 89
+Table 86 — Definition of TPMT_TK_VERIFIED Structure .......................................................................... 90
+Table 87 — Definition of TPMT_TK_AUTH Structure ................................................................................ 91
+Table 88 — Definition of TPMT_TK_HASHCHECK Structure .................................................................... 92
+Table 89 — Definition of TPMS_ALG_PROPERTY Structure <OUT> ....................................................... 92
+Table 90 — Definition of TPMS_TAGGED_PROPERTY Structure <OUT> ............................................... 92
+Table 91 — Definition of TPMS_TAGGED_PCR_SELECT Structure <OUT> ........................................... 93
+Table 92 — Definition of TPML_CC Structure ............................................................................................ 93
+Table 93 — Definition of TPML_CCA Structure <OUT> ............................................................................. 94
+Table 94 — Definition of TPML_ALG Structure .......................................................................................... 94
+Table 95 — Definition of TPML_HANDLE Structure <OUT>...................................................................... 94
+Table 96 — Definition of TPML_DIGEST Structure .................................................................................... 95
+Table 97 — Definition of TPML_DIGEST_VALUES Structure ................................................................... 95
+Table 98 — Definition of TPM2B_DIGEST_VALUES Structure ................................................................. 95
+Table 99 — Definition of TPML_PCR_SELECTION Structure ................................................................... 96
+Table 100 — Definition of TPML_ALG_PROPERTY Structure <OUT> ..................................................... 96
+Table 101 — Definition of TPML_TAGGED_TPM_PROPERTY Structure <OUT> ................................... 96
+Table 102 — Definition of TPML_TAGGED_PCR_PROPERTY Structure <OUT> ................................... 97
+Table 103 — Definition of {ECC} TPML_ECC_CURVE Structure <OUT> ................................................. 97
+Table 104 — Definition of TPMU_CAPABILITIES Union <OUT>............................................................... 97
+Table 105 — Definition of TPMS_CAPABILITY_DATA Structure <OUT> ................................................. 98
+Table 106 — Definition of TPMS_CLOCK_INFO Structure ........................................................................ 98
+Table 107 — Definition of TPMS_TIME_INFO Structure ........................................................................... 99
+Table 108 — Definition of TPMS_TIME_ATTEST_INFO Structure <OUT> ............................................. 100
+Table 109 — Definition of TPMS_CERTIFY_INFO Structure <OUT> ...................................................... 100
+Table 110 — Definition of TPMS_QUOTE_INFO Structure <OUT> ........................................................ 100
+Table 111 — Definition of TPMS_COMMAND_AUDIT_INFO Structure <OUT> ..................................... 101
+Table 112 — Definition of TPMS_SESSION_AUDIT_INFO Structure <OUT> ........................................ 101
+Table 113 — Definition of TPMS_CREATION_INFO Structure <OUT> .................................................. 101
+Table 114 — Definition of TPMS_NV_CERTIFY_INFO Structure <OUT> ............................................... 101
+Page xii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 115 — Definition of (TPM_ST) TPMI_ST_ATTEST Type <OUT> .................................................. 102
+Table 116 — Definition of TPMU_ATTEST Union <OUT> ....................................................................... 102
+Table 117 — Definition of TPMS_ATTEST Structure <OUT> .................................................................. 103
+Table 118 — Definition of TPM2B_ATTEST Structure <OUT> ................................................................ 103
+Table 119 — Definition of TPMS_AUTH_COMMAND Structure <IN> ..................................................... 104
+Table 120 — Definition of TPMS_AUTH_RESPONSE Structure <OUT> ................................................ 104
+Table 121 — Definition of {AES} (TPM_KEY_BITS) TPMI_AES_KEY_BITS Type ................................. 105
+Table 122 — Definition of {SM4} (TPM_KEY_BITS) TPMI_SM4_KEY_BITS Type ................................. 105
+Table 123 — Definition of TPMU_SYM_KEY_BITS Union ....................................................................... 106
+Table 124 — Definition of TPMU_SYM_MODE Union ............................................................................. 106
+Table 125 — xDefinition of TPMU_SYM_DETAILS Union ....................................................................... 107
+Table 126 — Definition of TPMT_SYM_DEF Structure ............................................................................ 107
+Table 127 — Definition of TPMT_SYM_DEF_OBJECT Structure ............................................................ 107
+Table 128 — Definition of TPM2B_SYM_KEY Structure .......................................................................... 108
+Table 129 — Definition of TPMS_SYMCIPHER_PARMS Structure ........................................................ 108
+Table 130 — Definition of TPM2B_SENSITIVE_DATA Structure ............................................................ 108
+Table 131 — Definition of TPMS_SENSITIVE_CREATE Structure <IN> ................................................ 109
+Table 132 — Definition of TPM2B_SENSITIVE_CREATE Structure <IN, S> .......................................... 110
+Table 133 — Definition of TPMS_SCHEME_SIGHASH Structure ........................................................... 110
+Table 134 — Definition of (TPM_ALG_ID) TPMI_ALG_KEYEDHASH_SCHEME Type .......................... 110
+Table 135 — Definition of Types for HMAC_SIG_SCHEME .................................................................... 110
+Table 136 — Definition of TPMS_SCHEME_XOR Structure ................................................................... 111
+Table 137 — Definition of TPMU_SCHEME_KEYEDHASH Union <IN/OUT, S> .................................... 111
+Table 138 — Definition of TPMT_KEYEDHASH_SCHEME Structure ..................................................... 111
+Table 139 — Definition of {RSA} Types for RSA_SIG_SCHEMES .......................................................... 112
+Table 140 — Definition of {ECC} Types for ECC_SIG_SCHEMES.......................................................... 112
+Table 141 — Definition of {ECC} TPMS_SCHEME_ECDAA Structure .................................................... 112
+Table 142 — Definition of TPMU_SIG_SCHEME Union <IN/OUT, S> .................................................... 113
+Table 143 — Definition of TPMT_SIG_SCHEME Structure ..................................................................... 113
+Table 144 — Definition of {RSA} TPMS_SCHEME_OAEP Structure ...................................................... 114
+Table 145 — Definition of {ECC} TPMS_SCHEME_ECDH Structure ...................................................... 114
+Table 146 — Definition of TPMS_SCHEME_MGF1 Structure ................................................................. 114
+Table 147 — Definition of {ECC} TPMS_SCHEME_KDF1_SP800_56a Structure .................................. 114
+Table 148 — Definition of TPMS_SCHEME_KDF2 Structure .................................................................. 115
+Table 149 — Definition of TPMS_SCHEME_KDF1_SP800_108 Structure ............................................. 115
+Table 150 — Definition of TPMU_KDF_SCHEME Union <IN/OUT, S> ................................................... 115
+Table 151 — Definition of TPMT_KDF_SCHEME Structure .................................................................... 115
+Table 152 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM_SCHEME Type <> ................................. 116
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xiii
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Table 153 — Definition of TPMU_ASYM_SCHEME Union ...................................................................... 116
+Table 154 — Definition of TPMT_ASYM_SCHEME Structure <> ............................................................ 117
+Table 155 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_SCHEME Type .............................. 117
+Table 156 — Definition of {RSA} TPMT_RSA_SCHEME Structure ......................................................... 117
+Table 157 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_DECRYPT Type ............................ 118
+Table 158 — Definition of {RSA} TPMT_RSA_DECRYPT Structure ....................................................... 118
+Table 159 — Definition of {RSA} TPM2B_PUBLIC_KEY_RSA Structure ................................................ 118
+Table 160 — Definition of {RSA} (TPM_KEY_BITS) TPMI_RSA_KEY_BITS Type ................................. 119
+Table 161 — Definition of {RSA} TPM2B_PRIVATE_KEY_RSA Structure .............................................. 119
+Table 162 — Definition of {ECC} TPM2B_ECC_PARAMETER Structure ............................................... 120
+Table 163 — Definition of {ECC} TPMS_ECC_POINT Structure ............................................................. 120
+Table 164 — Definition of {ECC} TPM2B_ECC_POINT Structure ........................................................... 120
+Table 165 — Definition of (TPM_ALG_ID) {ECC} TPMI_ALG_ECC_SCHEME Type ............................. 121
+Table 166 — Definition of {ECC} (TPM_ECC_CURVE) TPMI_ECC_CURVE Type ................................ 121
+Table 167 — Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure .................. 121
+Table 168 — Definition of {ECC} TPMS_ALGORITHM_DETAIL_ECC Structure <OUT> ....................... 122
+Table 169 — Definition of {RSA} TPMS_SIGNATURE_RSASSA Structure ............................................ 122
+Table 170 — Definition of {RSA} TPMS_SIGNATURE_RSAPSS Structure ............................................ 123
+Table 171 — Definition of {ECC} TPMS_SIGNATURE_ECDSA Structure .............................................. 123
+Table 172 — Definition of TPMU_SIGNATURE Union <IN/OUT, S> ....................................................... 123
+Table 173 — Definition of TPMT_SIGNATURE Structure ........................................................................ 124
+Table 174 — Definition of TPMU_ENCRYPTED_SECRET Union <S> ................................................... 124
+Table 175 — Definition of TPM2B_ENCRYPTED_SECRET Structure .................................................... 125
+Table 176 — Definition of (TPM_ALG_ID) TPMI_ALG_PUBLIC Type .................................................... 126
+Table 177 — Definition of TPMU_PUBLIC_ID Union <IN/OUT, S> ......................................................... 127
+Table 178 — Definition of TPMS_KEYEDHASH_PARMS Structure........................................................ 127
+Table 179 — Definition of TPMS_ASYM_PARMS Structure <> .............................................................. 128
+Table 180 — Definition of {RSA} TPMS_RSA_PARMS Structure ............................................................ 128
+Table 181 — Definition of {ECC} TPMS_ECC_PARMS Structure ........................................................... 129
+Table 182 — Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S> ................................................ 129
+Table 183 — Definition of TPMT_PUBLIC_PARMS Structure ................................................................. 130
+Table 184 — Definition of TPMT_PUBLIC Structure ................................................................................ 130
+Table 185 — Definition of TPM2B_PUBLIC Structure .............................................................................. 131
+Table 186 — Definition of {RSA} TPM2B_PRIVATE_VENDOR_SPECIFIC Structure<> ........................ 131
+Table 187 — Definition of TPMU_SENSITIVE_COMPOSITE Union <IN/OUT, S> ................................. 132
+Table 188 — Definition of TPMT_SENSITIVE Structure .......................................................................... 132
+Table 189 — Definition of TPM2B_SENSITIVE Structure <IN/OUT> ...................................................... 132
+Table 190 — Definition of _PRIVATE Structure <> .................................................................................. 133
+Table 191 — Definition of TPM2B_PRIVATE Structure <IN/OUT, S> ..................................................... 133
+Page xiv
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 192 — Definition of _ID_OBJECT Structure <> .............................................................................. 134
+Table 193 — Definition of TPM2B_ID_OBJECT Structure <IN/OUT> ..................................................... 134
+Table 194 — Definition of (UINT32) TPM_NV_INDEX Bits <> ................................................................. 135
+Table 195 — Options for space Field of TPM_NV_INDEX ....................................................................... 136
+Table 196 — Definition of (UINT32) TPMA_NV Bits ................................................................................ 137
+Table 197 — Definition of TPMS_NV_PUBLIC Structure ......................................................................... 139
+Table 198 — Definition of TPM2B_NV_PUBLIC Structure ....................................................................... 139
+Table 199 — Definition of TPM2B_CONTEXT_SENSITIVE Structure <IN/OUT> ................................... 140
+Table 200 — Definition of TPMS_CONTEXT_DATA Structure <IN/OUT, S> .......................................... 140
+Table 201 — Definition of TPM2B_CONTEXT_DATA Structure <IN/OUT> ............................................ 140
+Table 202 — Definition of TPMS_CONTEXT Structure ........................................................................... 141
+Table 203 — Context Handle Values ........................................................................................................ 142
+Table 204 — Definition of TPMS_CREATION_DATA Structure <OUT> ................................................. 144
+Table 205 — Definition of TPM2B_CREATION_DATA Structure <OUT> ............................................... 144
+Table 206 — Defines for SHA1 Hash Values ........................................................................................... 145
+Table 207 — Defines for SHA256 Hash Values ....................................................................................... 145
+Table 208 — Defines for SHA384 Hash Values ....................................................................................... 145
+Table 209 — Defines for SHA512 Hash Values ....................................................................................... 146
+Table 210 — Defines for SM3_256 Hash Values ..................................................................................... 146
+Table 211 — Defines for Architectural Limits Values ............................................................................... 146
+Table 212 — Defines for Logic Values ..................................................................................................... 147
+Table 213 — Defines for Processor Values .............................................................................................. 147
+Table 214 — Defines for Implemented Algorithms ................................................................................... 148
+Table 215 — Defines for Implemented Commands .................................................................................. 149
+Table 216 — Defines for RSA Algorithm Constants ................................................................................. 152
+Table 217 — Defines for ECC Algorithm Constants ................................................................................. 152
+Table 218 — Defines for AES Algorithm Constants ................................................................................. 152
+Table 219 — Defines for SM4 Algorithm Constants ................................................................................. 152
+Table 220 — Defines for Symmetric Algorithm Constants ....................................................................... 153
+Table 221 — Defines for Implementation Values ..................................................................................... 154
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xv
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Figures
+Figure 1 — Command Format .................................................................................................................... 22
+Figure 2 — Format-Zero Response Codes ................................................................................................. 29
+Figure 3 — Format-One Response Codes ................................................................................................. 30
+Figure 4 — TPM 1.2 TPM_NV_INDEX ..................................................................................................... 135
+Figure 5 — TPM 2.0 TPM_NV_INDEX ..................................................................................................... 135
+
+Page xvi
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Trusted Platform Module Library
+Part 2: Structures
+1
+
+Scope
+
+This part of the Trusted Platform Module Library specification contains the definitions of the constants,
+flags, structure, and union definitions used to communicate with the TPM. Values defined in this
+document are used by the TPM commands defined in part 3: Commands and by the functions in part 4:
+Supporting Routines.
+NOTE
+
+2
+
+The structures in this document are the canonical form of the structures on the interface. All structures
+are "packed" with no octets of padding between structure elements. The TPM-internal form of the
+structures is dependent on the processor and compiler for the TPM implementation.
+
+Terms and definitions
+
+For the purposes of this document, the terms and definitions given in part 1 of this specification apply.
+3
+
+Symbols and abbreviated terms
+
+For the purposes of this document, the symbols and abbreviated terms given in part 1 apply.
+4
+4.1
+
+Notation
+Introduction
+
+The information in this document is formatted so that it may be converted to standard computer-language
+formats by an automated process. The purpose of this automated process is to minimize the transcription
+errors that often occur during the conversion process.
+For the purposes of this document, the conventions given in Part 1 apply.
+In addition, the conventions and notations in this clause describe the representation of various data so
+that it is both human readable and amenable to automated processing.
+When a table row contains the keyword “reserved” (all lower case) in columns 1 or 2, the tools will not
+produce any values for the row in the table.
+NOTE 1
+
+In the examples in this clause 4, the unmarshaling routines are shown as returning bool. In the code of
+the reference implementation, the return value is a TPM_RC. A bool is used in the examples, because
+the meaning of a TPM_RC is not yet defined.
+
+NOTE 2
+
+The unmarshaling code examples are the actual code that would be produced by the automatic code
+generator used in the construction of the reference code. The actual code contains additional parameter
+checking that is omitted for clarity of the principle being illustrated. Actual examples of the code are found
+in Part 4.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 1
+October 31, 2013
+
+ Part 2: Structures
+4.2
+
+Trusted Platform Module Library
+
+Named Constants
+
+A named constant is a numeric value to which a name has been assigned. In the C language, this is done
+with a #define statement. In this specification, a named constant is defined in a table that has a title that
+starts with “Definition” and ends with “Constants.”
+The table title will indicate the name of the class of constants that are being defined in the table. The title
+will include the data type of the constants in parentheses.
+The table in Example 1 names a collection of 16-bit constants and Example 2 shows the C code that
+might be produced from that table by an automated process.
+NOTE
+
+A named constant (#define) has no data type in C and an enumeration would be a better choice for
+many of the defined constants. However, the C language does not allow an enumerated type to have a
+storage type other than int so the method of using a combination of typedef and #define is used.
+
+EXAMPLE 1
+
+Table xx — Definition of (UINT16) COUNTING Constants
+Parameter
+
+Value
+
+Description
+
+first
+
+1
+
+decimal value is implicitly the size of the
+
+second
+
+0x0002
+
+hex value will match the number of bits in the constant
+
+third
+
+3
+
+fourth
+
+0x0004
+
+EXAMPLE 2
+/* The C language equivalent of the constants from the table above */
+typedef
+UINT16
+COUNTING;
+#define
+first
+1
+#define
+second
+0x0002
+#define
+third
+3
+#define
+fourth
+0x0004
+
+Page 2
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+4.3
+
+Part 2: Structures
+
+Data Type Aliases (typedefs)
+
+When a group of named items is assigned a type, it is placed in a table that has a title starting with
+“Definition of Types.” In this specification, defined types have names that use all upper-case characters.
+The table in Example 1 shows how typedefs would be defined in this specification and Example 2 shows
+the C-compatible code that might be produced from that table by an automated process.
+EXAMPLE 1
+
+Table xx — Definition of Types for Some Purpose
+Type
+
+Name
+
+Description
+
+unsigned short
+
+UINT16
+
+UINT16
+
+SOME_TYPE
+
+unsigned long
+
+UINT32
+
+UINT32
+
+LAST_TYPE
+
+EXAMPLE 2
+/* C language equivalent of the typedefs from the table above */
+typedef unsigned short
+UINT16;
+typedef UINT16
+SOME_TYPE;
+typedef unsigned long
+UINT32;
+typedef UINT32
+LAST_TYPE;
+
+4.4
+
+Enumerations
+
+A table that defines an enumerated data type will start with the word “Definition” and end with “Values.”
+A value in parenthesis will denote the intrinsic data size of the value and may have the values "INT8",
+"UINT8", "INT16", “UINT16”, "INT32", and “UINT32.” If this value is not present, “UINT16” is assumed.
+Most C compilers set the type of an enumerated value to be an integer on the machine – often 16 bits –
+but this is not always consistent. To ensure interoperability, the enumeration values may not exceed
+32,384.
+The table in Example 1 shows how an enumeration would be defined in this specification. Example 2
+shows the C code that might be produced from that table by an automated process.
+EXAMPLE 1
+
+Table xx — Definition of (UINT16) CARD_SUIT Values
+Suit Names
+
+Value
+
+CLUBS
+
+0x0000
+
+DIAMONDS
+
+0x000D
+
+HEARTS
+
+0x001A
+
+SPADES
+
+Description
+
+0x0027
+
+EXAMPLE 2
+/* C language equivalent of the structure defined in the table above */
+typedef enum {
+CLUBS
+=
+0x0000,
+DIAMONDS
+=
+0x000D,
+HEARTS
+=
+0x001A,
+SPADES
+=
+0x0027
+} CARD_SUIT;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 3
+October 31, 2013
+
+ Part 2: Structures
+4.5
+
+Trusted Platform Module Library
+
+Interface Type
+
+An interface type is used for an enumeration that is checked by the unmarshaling code. This type is
+defined for purposes of automatic generation of the code that will validate the type. The title will start with
+the keyword “Definition” and end with the keyword “Type.” A value in parenthesis indicates the base type
+of the interface. The table may contain an entry that is prefixed with the “#” character to indicate the
+response code if the validation code determines that the input parameter is the wrong type.
+EXAMPLE 1
+
+Table xx — Definition of (CARD_SUIT) RED_SUIT Type
+Values
+
+Comments
+
+HEARTS
+DIAMONDS
+#TPM_RC_SUIT
+
+response code returned when the unmarshaling of this type fails
+NOTE
+
+TPM_RC_SUIT is an example and no such response
+code is actually defined in this specification.
+
+EXAMPLE 2
+/* Validation code that might be automatically generated from table above */
+if((*target != HEARTS) && (*target != DIAMONDS))
+return TPM_RC_SUIT;
+
+In some cases, the allowed values are numeric values with no associated mnemonic. In such a case, the
+list of numeric values may be given a name. Then, when used in an interface definition, the name would
+have a "$" prefix to indicate that a named list of values should be substituted.
+To illustrate, assume that the implementation only supports two sizes (1024 and 2048 bits) for keys
+associated with some algorithm (MY algorithm). In the implementation section (Annex B a named list
+would be created.
+EXAMPLE 3
+
+Table xx — Defines for MY Algorithm Constants
+Name
+
+Value
+
+Comments
+
+MY_KEY_SIZES_BITS
+
+{1024, 2048}
+
+braces because this is a list value
+
+Page 4
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Then, whenever an input value would need to be a valid MY key size for the implementation, the value
+$MY_KEY_SIZES_BITS could be used. Given the definition for MY_KEY_SIZES_BITS in example 3
+above, the tables in example 4 and 5 below, are equivalent.
+EXAMPLE 4
+
+Table xx — Definition of (UINT16) MY_KEY_BITS Type
+Parameter
+
+Description
+
+{1024, 2048}
+
+the number of bits in the supported key
+
+EXAMPLE 5
+
+Table xx — Definition of (UINT16) MY_KEY_BITS Type
+Parameter
+$MY_KEY_SIZES_BITS
+
+4.6
+
+Description
+the number of bits in the supported key
+
+Arrays
+
+Arrays are denoted by a value in square brackets (“[ ]”) following a parameter name. The value in the
+brackets may be either an integer value such as “[20]” or the name of a component of the same structure
+that contains the array.
+The table in Example 1 shows how a structure containing fixed and variable-length arrays would be
+defined in this specification. Example 2 shows the C code that might be produced from that table by an
+automated process.
+EXAMPLE 1
+
+Table xx — Definition of A_STRUCT Structure
+Parameter
+
+Type
+
+Description
+
+array1[20]
+
+UINT16
+
+an array of 20 UINT16s
+
+a_size
+
+UINT16
+
+array2[a_size]
+
+UINT32
+
+an array of UINT32 values that has a
+number of elements determined by a_size
+above
+
+EXAMPLE 2
+/* C language equivalent of the typedefs from the table above */
+typedef struct {
+UINT16
+array1[20];
+UINT16
+a_size;
+UINT32
+array2[];
+} A_STRUCT;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 5
+October 31, 2013
+
+ Part 2: Structures
+
+4.7
+
+Trusted Platform Module Library
+
+Structure Definitions
+
+The tables used to define structures have a title that starts with the word “Definition” and ends with
+“Structure.” The first column of the table will denote the reference names for the structure members; the
+second column the data type of the member; and the third column a synopsis of the use of the element.
+The table in Example 1 shows an example of how a structure would be defined in this specification and
+Example 2 shows the C code that might be produced from the table by an automated process. Example 3
+illustrates the type of unmarshaling code that could be generated using the information available in the
+table.
+EXAMPLE 1
+
+Table xx — Definition of SIMPLE_STRUCTURE Structure
+Parameter
+
+Type
+
+Description
+
+tag
+
+TPM_ST
+
+value1
+
+INT32
+
+value2
+
+INT32
+
+EXAMPLE 2
+/* C language equivalent of the structure defined in the table above */
+typedef struct {
+TPM_ST
+tag;
+INT32
+value1
+INT32
+value2;
+} SIMPLE_STRUCTURE;
+EXAMPLE 3
+bool SIMPLE_STRUCTURE_Unmarshal(SIMPLE_STRUCTURE *target, BYTE **buffer, INT32 *size)
+{
+// If unmarshal of tag succeeds
+if(TPM_ST_Unmarshal((TPM_ST *)&(target->tag), buffer, size))
+// then umarshal value1, and if that succeeds...
+if(INT32_Unmarshal((INT32 *)&(target->value1, buffer, size))
+// then return the results of unmarshaling values
+return(INT32_Unmarshal((INT32 *)&(target->value2, buffer, size))
+// if unmarshal of tag or value failed, return failure
+return FALSE;
+}
+
+Page 6
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+4.8
+
+Part 2: Structures
+
+Conditional Types
+
+An enumeration may contain an extended value indicated by “+” preceding the name in the "Value"
+column. This “+” indicates that this is a conditional value that may be allowed in certain situations.
+NOTE
+
+In many cases, the input values are algorithm IDs. When two collections of algorithm IDs differ only
+because one collection allows TPM_ALG_NULL and the other does not, it is preferred that the re not be
+two completely different enumerations because this leads to many casts. To avoid this, the “+” can be
+added to a TPM_ALG_NULL value in the table defining the type. When the use of that type allows
+TPM_ALG_NULL to be in the set, the use would append a “+” to the instance.
+
+EXAMPLE
+
+Table xx — Definition of (CARD_SUIT) TPMI_CARD_SUIT Type
+Values
+
+Comments
+
+SPADES
+HEARTS
+DIAMONDS
+CLUBS
++JOKER
+
+an optional value that may be allowed
+
+#TPM_RC_SUIT
+
+response code returned when the input value is not one of the
+values above
+
+When an interface type is used, a “+” will be appended to the type specification for the parameter when
+the conditional value is allowed. If no “+” is present, then the conditional value is not allowed.
+EXAMPLE 1
+
+Table xx — Definition of POKER_CARD Structure
+Parameter
+
+Type
+
+Description
+
+suit
+
+TPMI_CARD_SUIT+
+
+allows joker
+
+number
+
+UINT8
+
+the card value
+
+EXAMPLE 2
+
+Table xx — Definition of BRIDGE_CARD Structure
+Parameter
+
+Type
+
+Description
+
+suit
+
+TPMI_CARD_SUIT
+
+does not allow joker
+
+number
+
+UINT8
+
+the card value
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 7
+October 31, 2013
+
+ Part 2: Structures
+4.9
+
+Trusted Platform Module Library
+
+Unions
+
+4.9.1
+
+Introduction
+
+A union allows a structure to contain a variety of structures or types. The union has members, only one of
+which is present at a time. Three different tables are required to fully characterize a union so that it may
+be communicated on the TPM interface and used by the TPM:
+1) union definition;
+2) union instance; and
+3) union selector definition.
+4.9.2
+
+Union Definition
+
+The table in Example 1 illustrates a union definition. The title of a union definition table starts with
+“Definition” and ends with “Union.” The “Parameter” column of a union definition lists the different names
+that are used when referring a specific type. The “Type” column identifies the data type of the member.
+The “Selector” column identifies the value that is used by the marshaling and unmarshaling code to
+determine which case of the union is present.
+If a parameter is the keyword “null,” then this denotes a selector with no contents. The table in Example 1
+illustrates a union in which a conditional null selector is allowed to indicate an empty union member.
+Example 2 shows how the table would be converted into C-compatible code.
+The expectation is that the unmarshaling code for the union will validate that the selector for the union is
+one of values in the selector list.
+EXAMPLE 1
+
+Table xx — Definition of NUMBER_UNION Union
+Parameter
+
+Type
+
+Selector
+
+a_byte
+
+BYTE
+
+BYTE_SELECT
+
+an_int
+
+int
+
+INT_SELECT
+
+a_float
+
+float
+
+FLOAT_SELECT
+
++null
+
+NULL_SELECT
+
+Description
+
+the empty branch
+
+EXAMPLE 2
+// C-compatible version of the union defined in the table above
+typedef union {
+BYTE
+a_byte;
+int
+an_int;
+float
+a_float;
+} NUMBER_UNION;
+EXAMPLE 3
+
+Page 8
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+// Possible auto-generated code to unmarshal a union in Example 2 based on the
+// input value of selector
+bool NUMBER_UNION_Unmarshal(NUMBER_UNION *target, BYTE **buffer,
+INT32 *size, UINT32 selector)
+{
+switch (selector) {
+case BYTE_SELECT:
+return BYTE_Unmarshal((BYTE *)&(target->a_byte), buffer, size);
+case INT_SELECT:
+return INT_Unmarshal((int *)&(target->an_int), buffer, size);
+case FLOAT_SELECT:
+return FLOAT_Unmarshal((float *)&(target->a_float), buffer, size);
+case NULL_SELECT:
+return;
+}
+
+A table may have a type with no selector. This is used when the first part of the structure for all union
+members is identical. This type is a programming convenience, allowing code to reference the common
+members without requiring a case statement to determine the specific structure. In object oriented
+programming terms, this type is a superclass and the types with selectors are subclasses.
+4.9.3
+
+Union Instance
+
+When a union is used in a structure that is sent on the interface, the structure will minimally contain a
+selector and a union. The selector value indicates which of the possible union members is present so that
+the unmarshaling code can unmarshal the correct type. The selector may be any of the parameters that
+occur in the structure before the union instance. To denote the structure parameter that is used as the
+selector, its name is in brackets (“[ ]”) placed before the parameter name associated with the union.
+The table in Example 1 shows the definition of a structure that contains a union and a selector. Example 2
+shows how the table would be converted into C-compatible code and Example 3 shows how the
+unmarshaling code would handle the selector.
+EXAMPLE 1
+
+Table xx — Definition of STRUCTURE_WITH_UNION Structure
+Parameter
+
+Type
+
+Description
+
+select
+
+NUMBER_SELECT
+
+a value indicating the type in number
+
+[select] number
+
+NUMBER_UNION
+
+a union as shown in 4.9.2
+
+EXAMPLE 2
+// C-compatible version of the union structure in the table above
+typedef struct {
+NUMBER_SELECT
+select;
+NUMBER_UNION
+number;
+} STRUCT_WITH_UNION;
+EXAMPLE 3
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 9
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+// Possible unmarshaling code for the structure above
+bool STRUCT_WITH_UNION_Unmarshal(STRUCT_WITH_UNION *target, BYTE **buffer, INT32 *size)
+{
+// Unmarshal the selector value
+if(!NUMBER_SELECT_Unmarshal((NUMBER_SELECT *)&target->select, buffer, size))
+return FALSE;
+// Use the unmarshaled selector value to indicate to the union unmarshal
+// function which unmarshaling branch to follow.
+return(NUMBER_UNION_Unmarshal((NUMBER_UNION *)&(target->number),
+buffer, size, (UINT32)target->select);
+}
+
+4.9.4
+
+Union Selector Definition
+
+The selector definition limits the values that are used in unmarshaling a union. Two different selector sets
+applied to the same union define different types.
+For the union in 4.9.2, a selector definition should be limited to no more than four values, one for each of
+the union members. The selector definition could have fewer than four values.
+In Example 1, the table defines a value for each of the union members.
+EXAMPLE 1
+
+Table xx — Definition of (INT8) NUMBER_SELECT Values <IN>
+Name
+
+Value
+
+BYTE_SELECT
+
+3
+
+INT_SELECT
+
+2
+
+FLOAT_SELECT
+
+1
+
+NULL_SELECT
+
+Comments
+
+0
+
+The unmarshaling code would limit the input values to the defined values. When the NUMBER_SELECT
+is used in the union instance of 4.9.3, any of the allowed union members of NUMBER_UNION could be
+present.
+A different selection could be used to limit the values in a specific instance. To get the different selection,
+a new structure is defined with a different selector. The table in example 2 illustrates a way to subset the
+union. The base type of the selection is NUMBER_SELECT so a NUMBER_SELECT will be unmarshaled
+before the checks are made to see if the value is in the correct range for JUST_INTEGERS types. If the
+base type had been UINT8, then no checking would occur prior to checking that the value is in the
+allowed list. In this particular case, the effect is the same in either case since the only values that will be
+accepted by the unmarshaling code for JUST_INTEGER are BYTE_SELECT and INT_SELECT.
+EXAMPLE 2
+
+Table xx — Definition of (NUMBER_SELECT) AN_INTEGER Type <IN>
+Values
+{BYTE_SELECT, INT_SELECT}
+NOTE
+
+Comments
+list of allowed values
+
+Since NULL_SELECT is not in the list of values accepted as a JUST_INTEGER, the “+” modifier will have
+no effect if used for a JUST_INTEGERS type shown in Example 3.
+
+Page 10
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+The selector in Example 2 can then be used in a subset union as shown in Example 3.
+EXAMPLE 3
+
+Table xx — Definition of JUST_INTEGERS Structure
+Parameter
+
+Type
+
+Description
+
+select
+
+AN_INTEGER
+
+a value indicating the type in number
+
+[select] number
+
+NUMBER_UNION
+
+a union as shown in 4.9.2
+
+4.10 Bit Field Definitions
+A table that defines a structure containing bit fields has a title that starts with “Definition” and ends with
+“Bits.” A type identifier in parentheses in the title indicates the size of the datum that contains the bit
+fields.
+When the bit fields do not occupy consecutive locations, a spacer field is defined with a name of
+“Reserved.” Bits in these spaces are reserved and shall be zero.
+The table in Example 1 shows how a structure containing bit fields would be defined in this specification.
+Example 2 shows the C code that might be produced from that table by an automated process.
+When a field has more than one bit, the range is indicated by a pair of numbers separated by a colon (“:”).
+The numbers will be in high:low order.
+EXAMPLE1
+
+Table xx — Definition of (UINT32) SOME_ATTRIBUTE Bits
+Bit
+0
+
+Name
+
+Action
+
+zeroth_bit
+
+SET (1): what to do if bit is 1
+CLEAR (0): what to do if bit is 0
+
+1
+
+first_bit
+
+SET (1): what to do if bit is 1
+CLEAR (0): what to do if bit is 0
+
+6:2
+7
+
+Reserved
+
+A placeholder that spans 5 bits
+
+third_bit
+
+SET (1): what to do if bit is 1
+CLEAR (0): what to do if bit is 0
+
+31:8
+
+Reserved
+
+Placeholder to fill 32 bits
+
+EXAMPLE 2
+/* C language equivalent of the attributes structure defined in the table above */
+typedef struct {
+int zeroth_bit : 1;
+int first_bit : 1;
+int Reserved3 : 5;
+int third_bit : 1;
+int Reserved7 : 24;
+} SOME_ATTRIBUTE;
+
+4.11 Parameter Limits
+A parameter used in a structure may be given a set of values that can be checked by the unmarshaling
+code. The allowed values for a parameter may be included in the definition of the parameter by
+appending the values and delimiting them with braces (“{ }”). The values are comma-separated
+expressions. A range of numbers may be indicated by separating two expressions with a colon (“:”). The
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 11
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+first number is an expression that represents the minimum allowed value and the second number
+indicates the maximum. If the minimum or maximum value expression is omitted, then the range is openended.
+Parameter limits expressed using braces apply only to inputs to the TPM. Any value returned by the
+TPM is assumed to be valid.
+The maximum size of an array may be indicated by putting a “{}” delimited expression following the
+square brackets (“[ ]”) that indicate that the value is an array.
+EXAMPLE
+
+Table xx — Definition of B_STRUCT Structure
+Parameter
+
+Type
+
+Description
+
+value1 {20:25}
+
+UINT16
+
+a parameter that must have a value between 20
+and 25
+
+value2 {20}
+
+UINT16
+
+a parameter that must have a value of 20
+
+value3 {:25}
+
+INT16
+
+a parameter that may be no larger than 25
+Since the parameter is signed, the minimum value
+is the largest negative integer that may be
+expressed in 16 bits.
+
+value4 {20:}
+
+a parameter that must be at least 20
+
+value5 {1,2,3,5}
+
+UINT16
+
+a parameter that may only have one of the four
+listed values
+
+value6 {1, 2, 10:(10+10)}
+
+UINT32
+
+a parameter that may have a value of 1, 2, or be
+between 10 and 20
+
+array1[value1]
+
+BYTE
+
+Because the index refers to value1, which is a
+value limited to be between 20 and 25 inclusive,
+array1 is an array that may have between 20 and
+25 octets. This is not the preferred way to indicate
+the upper limit for an array as it does not indicate
+the upper bound of the size.
+NOTE
+
+array2[value4]{:25}
+
+BYTE
+
+This is a limitation of the current
+parser. A different parser could
+associate the range of value1 with this
+value and compute the maximum size
+of the array.
+
+an array that may have between 20 and 25 octets
+This arrangement is used to allow the automatic
+code generation to allocate 25 octets to store the
+largest array2 that can be unmarshaled. The code
+generation can determine from this expression that
+value4 shall have a value of 25 or less. From the
+definition of value4 above, it can determine that
+value4 must have a value of at least 20.
+
+Page 12
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+4.12 Enumeration Macro
+An enumeration can be a list of allowed numeric values. For example, the allowed sizes for an RSA key
+might be expressed as:
+
+4.13 Size Checking
+In some structures, a size field is present to indicate the number of octets in some subsequent part of the
+structure. In the B_STRUCT table in 4.11, value4 indicates how many octets to unmarshal for array2. This
+semantic applies when the size field determines the number of octets to unmarshal. However, in some
+cases, the subsequent structure is self-defining. If the size precedes a parameter that is not an octet
+array, then the unmarshaled size of that parameter is determined by its data type. The table in Example 1
+shows a structure where the size parameter would nominally indicate the number of octets in the
+remainder of the structure.
+EXAMPLE 1
+
+Table xx — Definition of C_STRUCT Structure
+Parameter
+
+Type
+
+Comments
+
+size
+
+UINT16
+
+the expected size of the remainder of the structure
+
+anInteger
+
+UINT32
+
+a 4-octet value
+
+In this particular case, the value of size would be incorrect if it had any value other than 4. So that the
+table parser is able to know that the purpose of the size parameter is to define the number of octets
+expected in the remainder of the structure, an equal sign (“=”) is appended to the parameter name.
+In the example below, the size= causes the parser to generate validation code that will check that the
+unmarshaled size of someStructure and someData adds to the value unmarshaled for size. When the “=”
+decoration is present, a value of zero is not allowed for the size.
+EXAMPLE 2
+
+Table xx — Definition of D_STRUCT Structure
+Parameter
+
+Type
+
+Comments
+
+size=
+
+UINT16
+
+the size of a structure
+The “=” indicates that the TPM is required to
+validate that the remainder of the D_STRUCT
+structure is exactly the value in size. That is, the
+number of bytes in the input buffer used to
+successfully unmarshal someStructure must be the
+same as size.
+
+someStructure
+
+A_STRUCT
+
+a structure to be unmarshaled
+The size of the structure is computed when it is
+unmarshaled. Because an “=” is present on the
+definition of size, the TPM is required to validate
+that the unmarshaled size exactly matches size.
+
+someData
+
+Family “2.0”
+Level 00 Revision 00.99
+
+UINT32
+
+a value
+
+Published
+Copyright © TCG 2006-2013
+
+Page 13
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+4.14 Data Direction
+A structure or union may be input (IN), output (OUT), or internal. An input structure is sent to the TPM and
+is unmarshaled by the TPM. An output structure is sent from the TPM and is marshaled by the TPM. An
+internal structure is not used outside of the TPM except that it may be included in a saved context.
+By default, structures are assumed to be both IN and OUT and the code generation tool will generate
+both marshaling and unmarshaling code for the structure. This default may be changed by using values
+enclosed in angle brackets (“<>”) as part of the table title. If the angle brackets are empty, then the
+structure is internal and neither marshaling nor unmarshaling code is generated. If the angle brackets
+contain the letter “I” (such as in “IN” or “in” or “i”), then the structure is input and unmarshaling code will be
+generated. If the angle brackets contain the letter “O” (such as in “OUT” or “out” or “o”), then the structure
+is output and marshaling code will be generated.
+EXAMPLE 1
+
+Both of the following table titles would indicate a structure that is used in both input and output
+Table xx — Definition of TPMS_A Structure
+Table xx — Definition of TPMS_A Structure <IN/OUT>
+
+EXAMPLE 2
+
+The following table title would indicate a structure that is used only for input
+Table xx — Definition of TPMS_A Structure <IN>
+
+EXAMPLE 3
+
+The following table title would indicate a structure that is used only for output
+Table xx — Definition of TPMS_A Structure <OUT>
+
+4.15 Structure Validations
+By default, when a structure is used for input to the TPM, the code generation tool will generate the
+unmarshaling code for that structure. Auto-generation may be suppressed by adding an “S” within the
+angle brackets.
+EXAMPLE
+
+The following table titles indicate a structure for which the auto -generation of the validation code is to be
+suppressed.
+Table xx — Definition of TPMT_A Structure <S>
+Table xx — Definition of TPMT_A Structure <IN, S>
+Table xx — Definition of TPMT_A Structure <IN/OUT, S>
+
+4.16 Name Prefix Convention
+Parameters are constants, variables, structures, unions, and structure members. Structure members are
+given a name that is indicative of its use, with no special prefix. The other parameter types are named
+according to their type with their name starting with “TPMx_”, where “x” is an optional character to indicate
+the data type.
+In some cases, additional qualifying characters will follow the underscore. These are generally used when
+dealing with an enumerated data type.
+TPMA_ This is an attribute structure, where bits are associated with particular attributes
+
+Page 14
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 1 — Name Prefix Convention
+Prefix
+
+Description
+
+_TPM_
+
+an indication/signal from the TPM’s system interface
+
+TPM_
+
+a constant or an enumerated type
+
+TPM2_
+
+a command defined by this specification
+
+TPM2B_
+
+a structure that is a sized buffer where the size of the buffer is contained in a 16-bit, unsigned
+value
+The first parameter is the size in octets of the second parameter. The second parameter may be
+any type.
+
+TPMA_
+
+a structure where each of the fields defines an attribute and each field is usually a single bit
+All the attributes in an attribute structure are packed with the overall size of the structure
+indicated in the heading of the attribute description (UINT8, UINT16, or UINT32).
+
+TPM_ALG_
+
+an enumerated type that indicates an algorithm
+A TPM_ALG_ is often used as a selector for a union.
+
+TPMI_
+
+an interface type
+The value is specified for purposes of dynamic type checking when unmarshaled.
+
+TPML_
+
+a list length followed by the indicated number of entries of the indicated type
+This is an array with a length field.
+
+TPMS_
+
+a structure that is not a size buffer or a tagged buffer or a list
+
+TPMT_
+
+a structure with the first parameter being a structure tag, indicating the type of the structure that
+follows
+A structure tag may be either a TPMT_ST_ or TPM_ALG_ depending on context.
+
+TPMU_
+
+a union of structures, lists, or unions
+If a union exists, there will normally be a companion TPMT_ that is the expression of the union
+in a tagged structure, where the tag is the selector indicating which member of the union is
+present.
+
+TPM_xx_
+
+an enumeration value of a particular type
+The value of “xx” will be indicative of the use of the enumerated type. A table of “TPM_xx”
+constant definitions will exist to define each of the TPM_xx_ values.
+EXAMPLE 1
+
+TPM_CC_ indicates that the type is used for a commandCode. The allowed enumeration
+values will be found in the table defining the TPM_CC constants (Table 11).
+
+EXAMPLE 2
+
+TPM_RC_ indicates that the type is used for a responseCode. The allowed enumeration
+values are in Table 15.
+
+4.17 Data Alignment
+The data structures in this Part 2 use octet alignment for all structures. When used in a table to indicate a
+maximum size, the sizeof() function returns the octet-aligned size of the structure, with no padding.
+4.18
+
+Parameter Unmarshaling Errors
+
+The TPM commands are defined in Part 3. The command definition included C code that details the
+actions performed by that command. The code is written assuming that the parameters of the command
+have been unmarshaled.
+NOTE 1
+
+An implementation is not required to process parameters in this manner or to separate the parameter
+parsing from the command actions. This method was chosen for the specification so that the normative
+behavior described by the detailed actions would be clear and unencumbered.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 15
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Unmarshaling is the process of processing the parameters in the input buffer and preparing the
+parameters for use by the command-specific action code. No data movement need take place but it is
+required that the TPM validate that the parameters meet the requirements of the expected data type as
+defined in this Part 2.
+When an error is encountered while unmarshaling a command parameter, an error response code is
+returned and no command processing occurs. A table defining a data type may have response codes
+embedded in the table to indicate the error returned when the input value does not match the parameters
+of the table.
+EXAMPLE 1
+
+Table 11 has a listing of TPM command code values. The last row in the table contains
+"#TPM_RC_COMMAND_CODE" indicating the response code that is returned if the TPM is unmarshaling
+a value that it expects to be a TPM_CC and the input value is not in the table.
+
+NOTE 2
+
+In the reference implementation, a parameter number is added to the response code so that the offending
+parameter can be isolated.
+
+In many cases, the table contains no specific response code value and the return code will be determined
+as defined in Table 2.
+Table 2 — Unmarshaling Errors
+Response code
+
+Usage
+
+TPM_RC_INSUFFICIENT
+
+the input buffer did not contain enough octets to allow unmarshaling of the
+expected data type;
+
+TPM_RC_RESERVED
+
+a non-zero value was found in a reserved field of an attribute structure (TPMA_)
+
+TPM_RC_SIZE
+
+the value of a size parameter is larger or smaller than allowed
+
+TPM_RC_VALUE
+
+A parameter does not have one of its allowed values
+
+TPM_RC_TAG
+
+A parameter that should be a structure tag has a value that is not supported by
+the TPM
+
+In some commands, a parameter may not be used because of various options of that command.
+However, the unmarshaling code is required to validate that all parameters have values that are allowed
+by the Part 2 definition of the parameter type even if that parameter is not used in the command actions.
+
+Page 16
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+5
+
+Part 2: Structures
+
+Base Types
+
+5.1
+
+Primitive Types
+
+The types listed in Table 3 are the primitive types on which all of the other types and structures are
+based. The values in the “Type” column should be edited for the compiler and computer on which the
+TPM is implemented. The values in the “Name” column should remain the same because these values
+are used in the remainder of the specification.
+NOTE
+
+The types are compatible with the C99 standard and should be defined in stdint.h that is provided with a
+C99-compliant compiler;
+
+The parameters in the Name column should remain in the order shown.
+Table 3 — Definition of Base Types
+Type
+
+Name
+
+Description
+
+uint8_t
+
+UINT8
+
+unsigned, 8-bit integer
+
+uint8_t
+
+BYTE
+
+unsigned 8-bit integer
+
+int8_t
+
+INT8
+
+signed, 8-bit integer
+
+int
+
+BOOL
+
+a bit in an int
+This is not used across the interface but is used in many places in the code. If
+the type were sent on the interface, it would have to have a type with a specific
+number of bytes.
+
+uint16_t
+
+UINT16
+
+unsigned, 16-bit integer
+
+int16_t
+
+INT16
+
+signed, 16-bit integer
+
+uint32_t
+
+UINT32
+
+unsigned, 32-bit integer
+
+int32_t
+
+INT32
+
+signed, 32-bit integer
+
+uint64_t
+
+UINT64
+
+unsigned, 64-bit integer
+
+int64_t
+
+INT64
+
+signed, 64-bit integer
+
+5.2
+
+Miscellaneous Types
+
+These types are defined either for compatibility with previous versions of this specification or for clarity of
+this specification.
+Table 4 — Definition of Types for Documentation Clarity
+Type
+
+Name
+
+Description
+
+UINT32
+
+TPM_ALGORITHM_ID
+
+this is the 1.2 compatible form of the TPM_ALG_ID
+
+UINT32
+
+TPM_MODIFIER_INDICATOR
+
+UINT32
+
+TPM_AUTHORIZATION_SIZE
+
+the authorizationSize parameter in a command
+
+UINT32
+
+TPM_PARAMETER_SIZE
+
+the parameterSizeset parameter in a command
+
+UINT16
+
+TPM_KEY_SIZE
+
+a key size in octets
+
+UINT16
+
+TPM_KEY_BITS
+
+a key size in bits
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 17
+October 31, 2013
+
+ Part 2: Structures
+
+6
+
+Trusted Platform Module Library
+
+Constants
+
+6.1
+
+TPM_SPEC (Specification Version Values)
+
+These values are readable with TPM2_GetCapability().
+NOTE
+
+This table will require editing when the specification is updated.
+
+Table 5 — Definition of (UINT32) TPM_SPEC Constants <>
+Name
+
+Value
+
+Comments
+ASCII “2.0” with null terminator
+
+TPM_SPEC_FAMILY
+
+0x322E3000
+
+TPM_SPEC_LEVEL
+
+00
+
+the level number for the specification
+
+TPM_SPEC_VERSION
+
+99
+
+the version number of the spec (00.99 * 100)
+
+TPM_SPEC_YEAR
+
+2013
+
+the year of the version
+
+TPM_SPEC_DAY_OF_YEAR
+
+304
+
+the day of the year (October 31, 2013)
+
+6.2
+
+TPM_GENERATED
+
+This constant value differentiates TPM-generated structures from non-TPM structures.
+Table 6 — Definition of (UINT32) TPM_GENERATED Constants <O>
+Name
+
+Value
+
+Comments
+
+TPM_GENERATED_VALUE
+
+0xff544347
+
+0xFF ‘TCG’ (FF 54 43 4716)
+
+Page 18
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.3
+
+Part 2: Structures
+
+TPM_ALG_ID
+
+The TCG maintains a registry of all algorithms that have an assigned algorithm ID. That registry is the
+definitive list of algorithms that may be supported by a TPM.
+NOTE
+
+Inclusion of an algorithm does NOT indicate that the necessary claims of the algorithm are av ailable
+under RAND terms from a TCG member.
+
+Table 7 is a copy of the TPM_ALG_ID constants table in the TCG registry as of the date of publication of
+this specification. Table 7 is provided for illustrative purposes only.
+{{Note for TCG Admin: Table 7 and the text in the paragraph above should be updated to reflect the final
+decisions by the TCG Board of Directors about inclusion of the table and the contents of the table. The
+desired approach is to leave the text as is and, immediately before publication of this specification for
+TCG admin to verify that Table 7 is the same as the algorithm registry table published by the TCG.}}
+An algorithm ID is often used like a tag to determine the type of a structure in a context-sensitive way.
+The values for TPM_ALG_ID shall be in the range of 00 0016 – 7F FF16. Other structure tags will be in the
+range 80 0016 – FF FF16.
+NOTE
+
+In TPM 1.2, these were defined as 32-bit constants. This specification limits the future size of the
+algorithm ID to 16 bits. The TPM_ALGORITHM_ID data type will continue to be a 32-bit number.
+
+An algorithm shall not be assigned a value in the range 00 C116 – 00 C616 in order to prevent any overlap
+with the command structure tags used in TPM 1.2.
+The implementation of some algorithms is dependent on the presence of other algorithms. When there is
+a dependency, the algorithm that is required is listed in column labeled "D" (dependent) in Table 7.
+EXAMPLE
+
+Implementation of TPM_ALG_RSASSA requires that the RSA algorithm be implemented.
+
+TPM_ALG_KEYEDHASH and TPM_ALG_NULL are required of all TPM implementations.
+Table 7 — Definition of (UINT16) TPM_ALG_ID Constants <IN/OUT, S>
+Algorithm Name
+
+Value
+
+Type
+
+a
+
+D
+
+Comments
+
+TPM_ALG_ERROR
+
+0x0000
+
+should not occur
+
+TPM_ALG_FIRST
+
+0x0001
+
+TPM_ALG_RSA
+
+0x0001
+
+AO
+
+the RSA algorithm
+
+TPM_ALG_SHA
+
+0x0004
+
+H
+
+the SHA1 algorithm
+
+TPM_ALG_SHA1
+
+0x0004
+
+H
+
+redefinition for documentation consistency
+OID 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 16
+
+TPM_ALG_HMAC
+
+0x0005
+
+HX
+
+the RFC 2104 Hash Message Authentication Code
+(HMAC) algorithm
+
+TPM_ALG_AES
+
+0x0006
+
+S
+
+the AES algorithm with a key size of 128 bits for TPM
+1.2
+the AES algorithm with multiple sizes of key for TPM
+2.0
+
+TPM_ALG_MGF1
+
+0x0007
+
+HM
+
+the mask-generation function defined in IEEE Std
+1363-2000
+
+TPM_ALG_KEYEDHASH
+
+0x0008
+
+HEXO
+
+an encryption or signing algorithm using a keyed hash,
+defined by TCG in the TPM 2.0 specification
+may also refer to a data object that is neither signing
+nor encrypting
+
+TPM_ALG_XOR
+
+0x000A
+
+HS
+
+marker value
+
+the XOR obfuscation algorithm
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+The implementation of XOR obfuscation in TPM
+2.0 is not the same as the XOR encryption
+method in TPM 1.2.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 19
+October 31, 2013
+
+ Part 2: Structures
+Algorithm Name
+
+Trusted Platform Module Library
+a
+
+Value
+
+Type
+
+TPM_ALG_SHA256
+
+0x000B
+
+H
+
+D
+
+Comments
+the SHA 256 algorithm
+OID 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05
+00 04 2016
+
+TPM_ALG_SHA384
+
+0x000C
+
+H
+
+the SHA 384 algorithm
+OID 30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05
+00 04 3016
+
+TPM_ALG_SHA512
+
+0x000D
+
+H
+
+the SHA 512 algorithm
+OID 30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05
+00 04 4016
+
+TPM_ALG_NULL
+
+0x0010
+
+TPM_ALG_SM3_256
+
+0x0012
+
+H
+
+hash algorithm standardized by OSCCA
+Block size is 512 bits.
+Output size is 256 bits.
+
+TPM_ALG_SM4
+
+0x0013
+
+S
+
+symmetric algorithm standardized by OSCCA
+Key and block size are 128 bits.
+
+TPM_ALG_RSASSA
+
+0x0014
+
+AX
+
+RSA a signature algorithm according to PKCS#1v2.1, 8.2
+
+TPM_ALG_RSAES
+
+0x0015
+
+AE
+
+RSA a padding algorithm according to PKCS#1v2.1, 7.2
+
+TPM_ALG_RSAPSS
+
+0x0016
+
+AX
+
+RSA signature algorithm (RSSASSA-PSS) according to
+PKCS#1v2.1, 8.1
+
+TPM_ALG_OAEP
+
+0x0017
+
+AE
+
+RSA padding algorithm
+PKCS#1v2.1, 7.1
+
+TPM_ALG_ECDSA
+
+0x0018
+
+AX
+
+ECC signature algorithm using elliptic curve cryptography
+(ECC)
+
+TPM_ALG_ECDH
+
+0x0019
+
+AM
+
+ECC secret sharing using ECC from SP800-56A
+Based on context, this can be either One-Pass DiffieHellman, C(1, 1, ECC CDH) defined in 6.2.2.2 or Full
+Unified Model C(2, 2, ECC CDH) defined in 6.1.1.2
+
+TPM_ALG_ECDAA
+
+0x001A
+
+AX
+
+ECC elliptic-curve based, anonymous signing scheme
+
+TPM_ALG_SM2
+
+0x001B
+
+AXE
+
+Null algorithm
+
+(RSAES_OAEP)
+
+according
+
+to
+
+ECC depending on context, either an elliptic-curve based,
+signature algorithm or a key exchange protocol
+NOTE
+
+This would be one of the algorithms specified in
+CM/T 0002 – 2012.
+
+TPM_ALG_ECSCHNORR
+
+0x001C
+
+AX
+
+ECC elliptic-curve-based Schnorr signature
+
+TPM_ALG_ECMQV
+
+0x001D
+
+AE
+
+ECC two-phase elliptic-curve key exchange -- C(2, 2, ECC
+MQV) from SP800-56A
+
+TPM_ALG_KDF1_SP800_56a
+
+0x0020
+
+HM
+
+ECC key derivation alternative #1 from SP800-56A
+
+TPM_ALG_KDF2
+
+0x0021
+
+HM
+
+key derivation function from IEEE Std 1363a-2004
+
+TPM_ALG_KDF1_SP800_108
+
+0x0022
+
+HM
+
+a key derivation method according to SP 800-108, "5.1
+KDF in Counter Mode”
+
+TPM_ALG_ECC
+
+0x0023
+
+AO
+
+prime field ECC
+
+TPM_ALG_SYMCIPHER
+
+0x0025
+
+O
+
+TPM_ALG_CTR
+
+0x0040
+
+SE
+
+Counter mode – if implemented, all symmetric block
+ciphers (S type) implemented shall be capable of using
+this mode.
+
+TPM_ALG_OFB
+
+0x0041
+
+SE
+
+Output Feedback mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+
+TPM_ALG_CBC
+
+0x0042
+
+SE
+
+Cipher Block Chaining mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+
+Page 20
+October 31, 2013
+
+the object type for a symmetric block cipher
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+a
+
+Algorithm Name
+
+Value
+
+Type
+
+TPM_ALG_CFB
+
+0x0043
+
+SE
+
+D
+
+Comments
+Cipher Feedback mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+
+TPM_ALG_ECB
+
+0x0044
+
+SE
+
+Electronic Codebook mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+NOTE
+
+This mode is not recommended for uses unless
+the key is frequently rotated such as in video
+codecs.
+
+TPM_ALG_LAST
+
+0x0044
+
+marker value
+
+reserved
+
+0x00C1
+
+0x00C1 – 0x00C6 are reserved
+
+reserved
+
+0x00C2
+
+reserved
+
+0x00C3
+
+reserved
+
+0x00C4
+
+reserved
+
+0x00C5
+
+reserved
+
+0x00C6
+
+NOTE a Column Indicates the algorithm type and use of the algorithm inside of the TPM. The values are:
+A – asymmetric algorithm with a public and private key
+S – symmetric algorithm with only a private key
+H – hash algorithm that compresses input data to a digest value
+X – signing algorithm
+E – an encryption algorithm
+M – a method such as a mask generation function
+O – an object type
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 21
+October 31, 2013
+
+ Part 2: Structures
+6.4
+
+Trusted Platform Module Library
+
+TPM_ECC_CURVE
+
+The TCG maintains a registry of all curves that have an assigned curve identifier. That registry is the
+definitive list of curves that may be supported by a TPM.
+Table 8 is a copy of the TPM_ECC_CURVE constants table in the TCG registry as of the date of
+publication of this specification. Table 8 is provided for illustrative purposes only.
+{{Note for TCG Admin: Table 8 and the text in the paragraph above should be updated to reflect the final
+decisions by the TCG Board of Directors about inclusion of the table and the contents of the table. The
+desired approach is to leave the text as is and, immediately before publication of this specification for
+TCG admin to verify that Table 8 is the same as the curve registry table published by the TCG.}}
+Table 8 — Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants <IN/OUT, S>
+Name
+
+Value
+
+Comments
+
+TPM_ECC_NONE
+
+0x0000
+
+TPM_ECC_NIST_P192
+
+0x0001
+
+TPM_ECC_NIST_P224
+
+0x0002
+
+TPM_ECC_NIST_P256
+
+0x0003
+
+TPM_ECC_NIST_P384
+
+0x0004
+
+TPM_ECC_NIST_P521
+
+0x0005
+
+TPM_ECC_BN_P256
+
+0x0010
+
+curve to support ECDAA
+
+TPM_ECC_BN_P638
+
+0x0011
+
+curve to support ECDAA
+
+TPM_ECC_SM2_P256
+
+0x0020
+
+#TPM_RC_CURVE
+
+6.5
+6.5.1
+
+TPM_CC (Command Codes)
+Format
+
+A command is a 32-bit structure with fields assigned as shown in Figure 1.
+3 3 2 2
+1 0 9 8
+
+Res V
+
+1 1
+6 5
+
+Reserved
+
+0
+0
+
+Command Index
+
+Figure 1 — Command Format
+Table 9 — TPM Command Format Fields Description
+Bit
+15:0
+
+Name
+
+Definition
+
+Command Index
+
+the index of the command
+
+28:16 Reserved
+29
+
+V
+
+31:30 Res
+
+Page 22
+October 31, 2013
+
+shall be zero
+SET(1): the command is vendor specific
+CLEAR(0): the command is not vendor specific
+shall be zero
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.5.2
+
+Part 2: Structures
+
+Description
+
+Table 10 provides the legend for the interpretation of the column data in Table 11.
+Table 10 — Legend for Command Code Tables
+Column
+
+Allowed
+Values
+
+Comments
+
+Name
+
+Command
+Code Name
+
+Name of the command
+
+Command Code
+
+Numeric value
+
+the numeric value for the commandCode
+
+NV Write
+
+blank, Y, O
+
+indicates whether the command may cause an NV write operation
+If this column contains a “Y,” then successful completion of the
+command is expected to cause modification of the NV memory
+because of the command actions.
+If the column contains an “O,” then the command may cause a
+modification to NV associated with an orderly shutdown. That is, the
+command may modify the orderly save state of NV, in which case, an
+NV write will be necessary.
+NOTE 1
+
+Any command may be delayed in order for the TPM to complete
+NV actions due to a previous command or because of an
+asynchronous update of Clock.
+
+NOTE 2
+
+Any command with an authorization value may cause an NV write
+on an authorization failure but the command does not complete
+successfully.
+
+If the entry is blank, then writing to NV is not allowed in the command
+actions.
+Physical Presence
+
+blank, Y
+
+indicates whether the platformAuth for this command may require
+confirmation through a physical presence indication
+
+Encrypted
+
+blank, 2, 4
+
+A numeric value that indicates the number of octets in the size field of
+the first parameter of a command
+Blank indicates that no size field is present and no parameter
+encryption is allowed.
+
+Encrypt
+
+blank, 2, 4
+
+A numeric value that indicates the number of octets in the size field of
+the first parameter of a response
+Blank indicates that no size field is present and no parameter
+encryption is allowed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 23
+October 31, 2013
+
+ Part 2: Structures
+6.5.3
+
+Trusted Platform Module Library
+
+TPM_CC Listing
+
+Table 11 lists the command codes and their attributes. The only normative column in this table is the
+column indicating the command code assigned to a specific command (the "Command Code" column).
+For all other columns, the command and response tables in Part 3 are definitive.
+
+Encrypt
+
+Encrypted
+
+Physical Presence
+
+NV Write
+
+Table 11 — Definition of (UINT32) TPM_CC Constants (Numeric Order) <IN/OUT, S>
+
+Name
+
+Command
+Code
+
+TPM_CC_FIRST
+
+0x0000011F
+
+Compile variable. May decrease
+based on implementation.
+
+TPM_CC_PP_FIRST
+
+0x0000011F
+
+Compile variable. Would decrease
+if new PP commands are added
+
+TPM_CC_NV_UndefineSpaceSpecial
+
+0x0000011F
+
+Y
+
+Y
+
+TPM_CC_EvictControl
+
+0x00000120
+
+Y
+
+Y
+
+TPM_CC_HierarchyControl
+
+0x00000121
+
+Y
+
+Y
+
+TPM_CC_NV_UndefineSpace
+
+0x00000122
+
+Y
+
+Y
+
+TPM_CC_ChangeEPS
+
+0x00000124
+
+Y
+
+Y
+
+TPM_CC_ChangePPS
+
+0x00000125
+
+Y
+
+Y
+
+TPM_CC_Clear
+
+0x00000126
+
+Y
+
+Y
+
+TPM_CC_ClearControl
+
+0x00000127
+
+Y
+
+Y
+
+TPM_CC_ClockSet
+
+0x00000128
+
+Y
+
+Y
+
+TPM_CC_HierarchyChangeAuth
+
+0x00000129
+
+Y
+
+Y
+
+2
+
+TPM_CC_NV_DefineSpace
+
+0x0000012A
+
+Y
+
+Y
+
+2
+
+TPM_CC_PCR_Allocate
+
+0x0000012B
+
+Y
+
+Y
+
+TPM_CC_PCR_SetAuthPolicy
+
+0x0000012C
+
+Y
+
+Y
+
+TPM_CC_PP_Commands
+
+0x0000012D
+
+Y
+
+Y
+
+TPM_CC_SetPrimaryPolicy
+
+0x0000012E
+
+Y
+
+Y
+
+2
+
+TPM_CC_FieldUpgradeStart
+
+0x0000012F
+
+O
+
+Y
+
+2
+
+TPM_CC_ClockRateAdjust
+
+0x00000130
+
+O
+
+Y
+
+TPM_CC_CreatePrimary
+
+0x00000131
+
+TPM_CC_NV_GlobalWriteLock
+
+0x00000132
+
+TPM_CC_PP_LAST
+
+0x00000132
+
+TPM_CC_GetCommandAuditDigest
+
+0x00000133
+
+Y
+
+TPM_CC_NV_Increment
+
+0x00000134
+
+Y
+
+Page 24
+October 31, 2013
+
+Y
+O
+
+Comments
+
+2
+
+2
+
+2
+
+Y
+Compile variable
+2
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Command
+Code
+
+TPM_CC_NV_SetBits
+
+0x00000135
+
+Y
+
+TPM_CC_NV_Extend
+
+0x00000136
+
+Y
+
+TPM_CC_NV_Write
+
+0x00000137
+
+Y
+
+TPM_CC_NV_WriteLock
+
+0x00000138
+
+Y
+
+TPM_CC_DictionaryAttackLockReset
+
+0x00000139
+
+O
+
+TPM_CC_DictionaryAttackParameters
+
+0x0000013A
+
+Y
+
+TPM_CC_NV_ChangeAuth
+
+0x0000013B
+
+Y
+
+2
+
+TPM_CC_PCR_Event
+
+0x0000013C
+
+O
+
+2
+
+TPM_CC_PCR_Reset
+
+0x0000013D
+
+O
+
+TPM_CC_SequenceComplete
+
+0x0000013E
+
+O
+
+TPM_CC_SetAlgorithmSet
+
+0x0000013F
+
+Y
+
+TPM_CC_SetCommandCodeAuditStatus
+
+0x00000140
+
+Y
+
+TPM_CC_FieldUpgradeData
+
+0x00000141
+
+O
+
+TPM_CC_IncrementalSelfTest
+
+0x00000142
+
+O
+
+TPM_CC_SelfTest
+
+0x00000143
+
+O
+
+TPM_CC_Startup
+
+0x00000144
+
+Y
+
+TPM_CC_Shutdown
+
+0x00000145
+
+Y
+
+TPM_CC_StirRandom
+
+0x00000146
+
+Y
+
+TPM_CC_ActivateCredential
+
+0x00000147
+
+TPM_CC_Certify
+
+0x00000148
+
+TPM_CC_PolicyNV
+
+0x00000149
+
+TPM_CC_CertifyCreation
+
+0x0000014A
+
+TPM_CC_Duplicate
+
+0x0000014B
+
+TPM_CC_GetTime
+
+0x0000014C
+
+O
+
+2
+
+TPM_CC_GetSessionAuditDigest
+
+0x0000014D
+
+O
+
+2
+
+TPM_CC_NV_Read
+
+0x0000014E
+
+TPM_CC_NV_ReadLock
+
+0x0000014F
+
+TPM_CC_ObjectChangeAuth
+
+0x00000150
+
+2
+
+TPM_CC_PolicySecret
+
+0x00000151
+
+2
+
+TPM_CC_Rewrap
+
+0x00000152
+
+2
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Encrypt
+
+Name
+
+NV Write
+
+Encrypted
+
+Part 2: Structures
+
+Physical Presence
+
+Trusted Platform Module Library
+
+2
+
+PCR
+PCR
+
+2
+
+2
+
+2
+
+2
+2
+
+O
+
+2
+
+2
+
+2
+
+2
+O
+
+Comments
+
+Policy
+
+2
+
+2
+
+2
+
+2
+
+2
+O
+
+Published
+Copyright © TCG 2006-2013
+
+2
+Policy
+2
+
+Page 25
+October 31, 2013
+
+ Trusted Platform Module Library
+
+Command
+Code
+
+Encrypt
+
+TPM_CC_Create
+
+0x00000153
+
+2
+
+2
+
+TPM_CC_ECDH_ZGen
+
+0x00000154
+
+2
+
+2
+
+TPM_CC_HMAC
+
+0x00000155
+
+2
+
+2
+
+TPM_CC_Import
+
+0x00000156
+
+2
+
+2
+
+TPM_CC_Load
+
+0x00000157
+
+2
+
+2
+
+TPM_CC_Quote
+
+0x00000158
+
+2
+
+2
+
+TPM_CC_RSA_Decrypt
+
+0x00000159
+
+TPM_CC_HMAC_Start
+
+0x0000015B
+
+2
+
+TPM_CC_SequenceUpdate
+
+0x0000015C
+
+2
+
+TPM_CC_Sign
+
+0x0000015D
+
+2
+
+TPM_CC_Unseal
+
+0x0000015E
+
+TPM_CC_PolicySigned
+
+0x00000160
+
+TPM_CC_ContextLoad
+
+0x00000161
+
+O
+
+Context
+
+TPM_CC_ContextSave
+
+0x00000162
+
+O
+
+Context
+
+TPM_CC_ECDH_KeyGen
+
+0x00000163
+
+2
+
+TPM_CC_EncryptDecrypt
+
+0x00000164
+
+2
+
+TPM_CC_FlushContext
+
+0x00000165
+
+TPM_CC_LoadExternal
+
+0x00000167
+
+2
+
+2
+
+TPM_CC_MakeCredential
+
+0x00000168
+
+2
+
+2
+
+TPM_CC_NV_ReadPublic
+
+0x00000169
+
+TPM_CC_PolicyAuthorize
+
+0x0000016A
+
+TPM_CC_PolicyAuthValue
+
+0x0000016B
+
+Policy
+
+TPM_CC_PolicyCommandCode
+
+0x0000016C
+
+Policy
+
+TPM_CC_PolicyCounterTimer
+
+0x0000016D
+
+2
+
+Policy
+
+TPM_CC_PolicyCpHash
+
+0x0000016E
+
+2
+
+Policy
+
+TPM_CC_PolicyLocality
+
+0x0000016F
+
+TPM_CC_PolicyNameHash
+
+0x00000170
+
+TPM_CC_PolicyOR
+
+0x00000171
+
+TPM_CC_PolicyTicket
+
+0x00000172
+
+TPM_CC_ReadPublic
+
+0x00000173
+
+Page 26
+October 31, 2013
+
+NV Write
+
+Name
+
+Encrypted
+
+Physical Presence
+
+Part 2: Structures
+
+O
+
+Comments
+
+2
+2
+
+2
+2
+
+Policy
+
+O
+
+Context
+
+NV
+2
+
+Policy
+
+Policy
+2
+
+Policy
+Policy
+
+2
+
+Published
+Copyright © TCG 2006-2013
+
+Policy
+2
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Encrypt
+
+2
+
+NV Write
+
+Encrypted
+
+Part 2: Structures
+
+Physical Presence
+
+Trusted Platform Module Library
+
+2
+
+2
+
+2
+
+Name
+
+Command
+Code
+
+TPM_CC_RSA_Encrypt
+
+0x00000174
+
+TPM_CC_StartAuthSession
+
+0x00000176
+
+TPM_CC_VerifySignature
+
+0x00000177
+
+TPM_CC_ECC_Parameters
+
+0x00000178
+
+TPM_CC_FirmwareRead
+
+0x00000179
+
+TPM_CC_GetCapability
+
+0x0000017A
+
+TPM_CC_GetRandom
+
+0x0000017B
+
+TPM_CC_GetTestResult
+
+0x0000017C
+
+TPM_CC_Hash
+
+0x0000017D
+
+TPM_CC_PCR_Read
+
+0x0000017E
+
+PCR
+
+TPM_CC_PolicyPCR
+
+0x0000017F
+
+Policy
+
+TPM_CC_PolicyRestart
+
+0x00000180
+
+TPM_CC_ReadClock
+
+0x00000181
+
+TPM_CC_PCR_Extend
+
+0x00000182
+
+O
+
+2
+
+TPM_CC_PCR_SetAuthValue
+
+0x00000183
+
+N
+
+2
+
+TPM_CC_NV_Certify
+
+0x00000184
+
+O
+
+TPM_CC_EventSequenceComplete
+
+0x00000185
+
+O
+
+TPM_CC_HashSequenceStart
+
+0x00000186
+
+TPM_CC_PolicyPhysicalPresence
+
+0x00000187
+
+Policy
+
+TPM_CC_PolicyDuplicationSelect
+
+0x00000188
+
+Policy
+
+TPM_CC_PolicyGetDigest
+
+0x00000189
+
+Policy
+
+TPM_CC_TestParms
+
+0x0000018A
+
+TPM_CC_Commit
+
+0x0000018B
+
+TPM_CC_PolicyPassword
+
+0x0000018C
+
+TPM_CC_ZGen_2Phase
+
+0x0000018D
+
+TPM_CC_EC_Ephemeral
+
+0x0000018E
+
+TPM_CC_PolicyNvWritten
+
+0x0000018F
+
+Policy
+
+TPM_CC_LAST
+
+0x0000018F
+
+Compile variable. May increase
+based on implementation.
+
+O
+
+Comments
+
+2
+
+2
+
+2
+
+O
+
+2
+
+2
+
+2
+Policy
+
+2
+
+2
+
+NOTE
+
+#TPM_RC_COMMAND_CODE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+This is not a FMT1 code
+and a parameter indicator
+value may not be added to
+
+Page 27
+October 31, 2013
+
+ Encrypt
+
+Encrypted
+
+Command
+Code
+
+Name
+
+Physical Presence
+
+Trusted Platform Module Library
+
+NV Write
+
+Part 2: Structures
+
+Comments
+this value.
+
+6.6
+
+TPM_RC (Response Codes)
+
+6.6.1
+
+Description
+
+Each return from the TPM has a 32-bit response code. The TPM will always set the upper 20 bits (31:12)
+of the response code to 0 00 0016 and the low-order 12 bits (11:00) will contain the response code.
+When a command succeeds, the TPM shall return TPM_RC_SUCCESS (0 0016) and will update any
+authorization-session nonce associated with the command.
+When a command fails to complete for any reason, the TPM shall return
+
+
+a TPM_ST (UINT16) with a value of TPM_TAG_RSP_COMMAND or TPM_ST_NO_SESSIONS,
+followed by
+
+
+
+a UINT32 (responseSize) with a value of 10, followed by
+
+
+
+a UINT32 containing a response code with a value other than TPM_RC_SUCCESS.
+
+Commands defined in this specification will use a tag of either TPM_ST_NO_SESSIONS or
+TPM_ST_SESSIONS. Error responses will use a tag value of TPM_ST_NO_SESSIONS and the
+response code will be as defined in this specification. Commands that use tags defined in the TPM 1.2
+specification will use TPM_TAG_RSP_COMMAND in an error and a response code defined in TPM 1.2.
+If the tag of the command is not a recognized command tag, the TPM error response will differ depending
+on TPM 1.2 compatibility. If the TPM supports 1.2 compatibility, the TPM shall return a tag of
+TPM_TAG_RSP_COMMAND and an appropriate TPM 1.2 response code (TPM_BADTAG =
+00 00 00 1E16). If the TPM does not have compatibility with TPM 1.2, the TPM shall return
+TPM_ST_NO_SESSION and a response code of TPM_RC_TAG.
+When a command fails, the TPM shall not update the authorization-session nonces associated with the
+command and will not close the authorization sessions used by the command. Audit digests will not be
+updated on an error. Unless noted in the command actions, a command that returns an error shall leave
+the state of the TPM as if the command had not been attempted. The exception to this principle is that a
+failure due to an authorization failure may update the dictionary-attack protection values.
+
+Page 28
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.6.2
+
+Part 2: Structures
+
+Response Code Formats
+
+The response codes for this specification are defined such that there is no overlap between the response
+codes used for this specification and those assigned in previous TPM specifications.
+The formats defined in this clause only apply when the tag for the response is TPM_ST_NO_SESSIONS.
+The response codes use two different format groups. One group contains the TPM 1.2 compatible
+response codes and the response codes for this specification that are not related to command
+parameters. The second group contains the errors that may be associated with a command parameter,
+handle, or session.
+Figure 2 shows the format for the response codes when bit 7 is zero.
+1
+1
+
+1
+0
+
+0
+9
+
+0
+8
+
+0
+7
+
+S
+
+bit
+
+T
+
+r
+
+V
+
+0
+6
+
+0
+5
+
+F
+
+0
+4
+
+0
+3
+
+0
+2
+
+0
+1
+
+0
+0
+
+E
+
+Figure 2 — Format-Zero Response Codes
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 29
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+The field definitions are:
+Table 12 — Format-Zero Response Codes
+Bit
+
+Name
+
+Definition
+
+06:00
+
+E
+
+the error number
+The interpretation of this field is dependent on the setting of the G and S fields.
+
+07
+
+F
+
+format selector
+CLEAR when the format is as defined in this Table 12 or when the response code is
+TPM_RC_BAD_TAG.
+
+08
+
+V
+
+version
+SET (1): The error number is defined in this specification and is returned when the response tag
+is TPM_ST_NO_SESSIONS.
+CLEAR (0): The error number is defined by a previous TPM specification. The error number is
+returned when the response tag is TPM_TAG_RSP_COMMAND.
+NOTE
+
+09
+
+In any error number returned by a TPM, the F (bit 7) and V (bit 8) attributes shall be CLEAR
+when the response tag is TPM_TAG_RSP_COMMAND value used in TPM 1.2.
+
+Reserved shall be zero.
+
+10
+
+T
+
+TCG/Vendor indicator
+SET (1): The response code is defined by the TPM vendor.
+CLEAR (0): The response code is defined by the TCG (a value in this specification).
+NOTE
+
+11
+
+S
+
+This attribute does not indicate a vendor-specific code unless the F attribute (bit[07]) is CLEAR.
+
+severity
+SET (1): The response code is a warning and the command was not necessarily in error. This
+command indicates that the TPM is busy or that the resources of the TPM have to be adjusted in
+order to allow the command to execute.
+CLEAR (0): The response code indicates that the command had an error that would prevent it
+from running.
+
+When the format bit (bit 7) is SET, then the error occurred during the unmarshaling or validation of an
+input parameter to the TPM. Figure 3 shows the format for the response codes when bit 7 is one.
+bit
+
+1
+1
+
+1
+0
+
+0
+9
+
+N
+
+0
+8
+
+0
+7
+
+0
+6
+
+1
+
+0
+5
+
+P
+
+0
+4
+
+0
+3
+
+0
+2
+
+0
+1
+
+0
+0
+
+E
+
+Figure 3 — Format-One Response Codes
+There are 64 errors with this format. The errors can be associated with a parameter, handle, or session.
+The error number for this format is in bits[05:00]. When an error is associated with a parameter, 0 40 16 is
+added and N is set to the parameter number.
+For an error associated with a handle, a parameter number (1 to 7) is added to the N field. For an error
+associated with a session, a value of 8 plus the session number (1 to 7) is added to the N field. In other
+words, if P is clear, then a value of 0 to 7 in the N field will indicate a handle error, and a value of 8 – 15
+will indicate a session error.
+NOTE
+
+If an implementation is not able to designate the handle, session, or parameter in error, then P and N will
+be zero.
+
+Page 30
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+The field definitions are:
+Table 13 — Format-One Response Codes
+Bit
+
+Name Definition
+
+05:00
+
+E
+
+the error number
+The error number is independent of the other settings.
+
+06
+
+P
+
+SET (1): The error is associated with a parameter.
+CLEAR (0): The error is associated with a handle or a session.
+
+07
+
+F
+
+the response code format selector
+This field shall be SET for the format in this table.
+
+11:08
+
+N
+
+the number of the handle, session, or parameter in error
+If P is SET, then this field is the parameter in error. If P is CLEAR, then this field indicates the
+handle or session in error. Handles use values of N between 0000 2 and 01112. Sessions use
+values between 10002 and 11112.
+
+The groupings of response codes are determined by bits 08, 07, and 06 of the response code as
+summarized in Table 14.
+Table 14 — Response Code Groupings
+Bit
+0
+8
+
+0
+7
+
+0
+6
+
+Definition
+
+0
+
+0
+
+x
+
+a response code defined by TPM 1.2
+NOTE
+
+An “x” in a column indicates that this may be either 0 or 1 and not affect the grouping of the response
+code.
+
+1
+
+0
+
+x
+
+a response code defined by this specification with no handle, session, or parameter number modifier
+
+x
+
+1
+
+0
+
+a response code defined by this specification with either a handle or session number modifier
+
+x
+
+1
+
+1
+
+a response code defined by this specification with a parameter number modifier
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 31
+October 31, 2013
+
+ Part 2: Structures
+6.6.3
+
+Trusted Platform Module Library
+
+TPM_RC Values
+
+In general, response codes defined in Part 2 will be unmarshaling errors and will have the F (format) bit
+SET. Codes that are unique to Part 3 will have the F bit CLEAR but the V (version) attribute will be SET to
+indicate that it is a TPM 2.0 response code.
+NOTE
+
+The constant RC_VER1 is used to indicate that the V attribute is SET and the constant RC_ FMT1 is used
+to indicate that the F attribute is SET and that the return code is variable based on handle, session, and
+parameter modifiers.
+
+Table 15 — Definition of (UINT32) TPM_RC Constants (Actions) <OUT>
+Name
+
+Value
+
+Description
+
+TPM_RC_SUCCESS
+
+0x000
+
+TPM_RC_BAD_TAG
+
+0x01E
+
+defined for compatibility with TPM 1.2
+
+RC_VER1
+
+0x100
+
+set for all format 0 response codes
+
+TPM_RC_INITIALIZE
+
+RC_VER1 + 0x000
+
+TPM not initialized
+commands not being accepted because of a TPM
+failure
+
+TPM_RC_FAILURE
+
+RC_VER1 + 0x001
+
+NOTE
+
+TPM_RC_SEQUENCE
+
+RC_VER1 + 0x003
+
+improper use of a sequence handle
+
+TPM_RC_PRIVATE
+
+RC_VER1 + 0x00B
+
+TPM_RC_HMAC
+
+RC_VER1 + 0x019
+
+TPM_RC_DISABLED
+
+RC_VER1 + 0x020
+
+TPM_RC_EXCLUSIVE
+
+RC_VER1 + 0x021
+
+command failed because audit sequence required
+exclusivity
+
+TPM_RC_AUTH_TYPE
+
+RC_VER1 + 0x024
+
+authorization handle is not correct for command
+
+TPM_RC_AUTH_MISSING
+
+RC_VER1 + 0x025
+
+command requires an authorization session for
+handle and it is not present.
+
+TPM_RC_POLICY
+
+RC_VER1 + 0x026
+
+policy Failure In Math Operation or an invalid
+authPolicy value
+
+TPM_RC_PCR
+
+RC_VER1 + 0x027
+
+PCR check fail
+
+TPM_RC_PCR_CHANGED
+
+RC_VER1 + 0x028
+
+PCR have changed since checked.
+
+TPM_RC_UPGRADE
+
+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
+
+TPM_RC_TOO_MANY_CONTEXTS
+
+RC_VER1 + 0x02E
+
+context ID counter is at maximum.
+
+TPM_RC_AUTH_UNAVAILABLE
+
+RC_VER1 + 0x02F
+
+authValue or authPolicy is not available for
+selected entity.
+
+TPM_RC_REBOOT
+
+RC_VER1 + 0x030
+
+a _TPM_Init and Startup(CLEAR) is required
+before the TPM can resume operation.
+
+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.
+
+TPM_RC_UNBALANCED
+
+Page 32
+October 31, 2013
+
+This
+may
+be
+returned
+by
+TPM2_GetTestResult() as the testResult
+parameter.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Name
+
+Part 2: Structures
+Value
+
+Description
+
+TPM_RC_COMMAND_SIZE
+
+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
+
+TPM_RC_COMMAND_CODE
+
+RC_VER1 + 0x043
+
+command code not supported
+
+TPM_RC_AUTHSIZE
+
+RC_VER1 + 0x044
+
+the value of authorizationSize is out of range or the
+number of octets in the Authorization Area is
+greater than required
+
+TPM_RC_AUTH_CONTEXT
+
+RC_VER1 + 0x045
+
+use of an authorization session with a context
+command
+
+TPM_RC_NV_RANGE
+
+RC_VER1 + 0x046
+
+NV offset+size is out of range.
+
+TPM_RC_NV_SIZE
+
+RC_VER1 + 0x047
+
+Requested allocation size is larger than allowed.
+
+TPM_RC_NV_LOCKED
+
+RC_VER1 + 0x048
+
+NV access locked.
+
+TPM_RC_NV_AUTHORIZATION
+
+RC_VER1 + 0x049
+
+NV access authorization fails in command actions
+(this failure does not affect lockout.action)
+
+TPM_RC_NV_UNINITIALIZED
+
+RC_VER1 + 0x04A
+
+an NV Index is used before being initialized or the
+state saved by TPM2_Shutdown(STATE) could not
+be restored
+
+TPM_RC_NV_SPACE
+
+RC_VER1 + 0x04B
+
+insufficient space for NV allocation
+
+TPM_RC_NV_DEFINED
+
+RC_VER1 + 0x04C
+
+NV Index or persistend object already defined
+
+TPM_RC_BAD_CONTEXT
+
+RC_VER1 + 0x050
+
+context in TPM2_ContextLoad() is not valid
+
+TPM_RC_CPHASH
+
+RC_VER1 + 0x051
+
+cpHash value already set or not correct for use
+
+TPM_RC_PARENT
+
+RC_VER1 + 0x052
+
+handle for parent is not a valid parent
+
+TPM_RC_NEEDS_TEST
+
+RC_VER1 + 0x053
+
+some function needs testing.
+
+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.
+
+TPM_RC_SENSITIVE
+
+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
+
+RC_MAX_FM0
+
+RC_VER1 + 0x07F
+
+largest version 1 code that is not a warning
+
+TPM_RC_NO_RESULT
+
+New Subsection
+
+RC_FMT1
+
+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.
+
+TPM_RC_ASYMMETRIC
+
+RC_FMT1 + 0x001
+
+asymmetric algorithm not supported or not correct
+
+TPM_RC_ATTRIBUTES
+
+RC_FMT1 + 0x002
+
+inconsistent attributes
+
+TPM_RC_HASH
+
+RC_FMT1 + 0x003
+
+hash algrithm not supported or not appropriate
+
+TPM_RC_VALUE
+
+RC_FMT1 + 0x004
+
+value is out of range or is not correct for the
+context
+
+TPM_RC_HIERARCHY
+
+RC_FMT1 + 0x005
+
+hierarchy is not enabled or is not correct for the
+use
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 33
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Name
+
+Value
+
+Description
+
+TPM_RC_KEY_SIZE
+
+RC_FMT1 + 0x007
+
+key size is not supported
+
+TPM_RC_MGF
+
+RC_FMT1 + 0x008
+
+mask generation function not supported
+
+TPM_RC_MODE
+
+RC_FMT1 + 0x009
+
+mode of operation not supported
+
+TPM_RC_TYPE
+
+RC_FMT1 + 0x00A
+
+the type of the value is not appropriate for the use
+
+TPM_RC_HANDLE
+
+RC_FMT1 + 0x00B
+
+the handle is not correct for the use
+
+TPM_RC_KDF
+
+RC_FMT1 + 0x00C
+
+unsupported key derivation function or function not
+appropriate for use
+
+TPM_RC_RANGE
+
+RC_FMT1 + 0x00D
+
+value was out of allowed range.
+
+TPM_RC_AUTH_FAIL
+
+RC_FMT1 + 0x00E
+
+the authorization HMAC check failed and DA
+counter incremented
+
+TPM_RC_NONCE
+
+RC_FMT1 + 0x00F
+
+invalid nonce size
+
+TPM_RC_PP
+
+RC_FMT1 + 0x010
+
+authorization requires assertion of PP
+
+TPM_RC_SCHEME
+
+RC_FMT1 + 0x012
+
+unsupported or incompatible scheme
+
+TPM_RC_SIZE
+
+RC_FMT1 + 0x015
+
+structure is the wrong size
+
+TPM_RC_SYMMETRIC
+
+RC_FMT1 + 0x016
+
+unsupported symmetric algorithm or key size, or
+not appropriate for instance
+
+TPM_RC_TAG
+
+RC_FMT1 + 0x017
+
+incorrect structure tag
+
+TPM_RC_SELECTOR
+
+RC_FMT1 + 0x018
+
+union selector is incorrect
+
+TPM_RC_INSUFFICIENT
+
+RC_FMT1 + 0x01A
+
+the TPM was unable to unmarshal a value
+because there were not enough octets in the input
+buffer
+
+TPM_RC_SIGNATURE
+
+RC_FMT1 + 0x01B
+
+the signature is not valid
+
+TPM_RC_KEY
+
+RC_FMT1 + 0x01C
+
+key fields are not compatible with the selected use
+
+TPM_RC_POLICY_FAIL
+
+RC_FMT1 + 0x01D
+
+a policy check failed
+
+TPM_RC_INTEGRITY
+
+RC_FMT1 + 0x01F
+
+integrity check failed
+
+TPM_RC_TICKET
+
+RC_FMT1 + 0x020
+
+invalid ticket
+
+TPM_RC_RESERVED_BITS
+
+RC_FMT1 + 0x021
+
+reserved bits not set to zero as required
+
+TPM_RC_BAD_AUTH
+
+RC_FMT1 + 0x022
+
+authroization failure without DA implications
+
+TPM_RC_EXPIRED
+
+RC_FMT1 + 0x023
+
+the policy has expired
+
+TPM_RC_POLICY_CC
+
+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
+
+TPM_RC_BINDING
+
+RC_FMT1 + 0x025
+
+public and sensitive portions of an object are not
+cryptographically bound
+
+TPM_RC_CURVE
+
+RC_FMT1 + 0x026
+
+curve not supported
+
+TPM_RC_ECC_POINT
+
+RC_FMT1 + 0x027
+
+point is not on the required curve.
+
+New Subsection
+RC_WARN
+
+0x900
+
+set for warning response codes
+
+TPM_RC_CONTEXT_GAP
+
+RC_WARN + 0x001
+
+gap for context ID is too large
+
+TPM_RC_OBJECT_MEMORY
+
+RC_WARN + 0x002
+
+out of memory for object contexts
+
+Page 34
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Name
+
+Value
+
+Description
+
+TPM_RC_SESSION_MEMORY
+
+RC_WARN + 0x003
+
+out of memory for session contexts
+
+TPM_RC_MEMORY
+
+RC_WARN + 0x004
+
+out of shared object/session memory or need
+space for internal operations
+
+TPM_RC_SESSION_HANDLES
+
+RC_WARN + 0x005
+
+out of session handles – a session must be flushed
+before a new session may be created
+out of object handles – the handle space for
+objects is depleted and a reboot is required
+NOTE
+
+TPM_RC_LOCALITY
+
+TPM_RC_YIELDED
+
+This cannot occur
+implementation.
+
+NOTE
+
+TPM_RC_OBJECT_HANDLES
+
+There is no reason why an implementation
+would implement a design that would deplete
+handle space. Platform specifications are
+encouraged to forbid it.
+
+RC_WARN + 0x006
+
+RC_WARN + 0x007
+
+RC_WARN + 0x008
+
+on
+
+the
+
+reference
+
+bad locality
+the TPM has suspended operation on the
+command; forward progress was made and the
+command may be retried.
+See Part 1, “Multi-tasking.”
+NOTE
+
+This cannot occur
+implementation.
+
+on
+
+the
+
+reference
+
+TPM_RC_CANCELED
+
+RC_WARN + 0x009
+
+the command was canceled
+
+TPM_RC_TESTING
+
+RC_WARN + 0x00A
+
+TPM is performing self-tests
+
+TPM_RC_REFERENCE_H0
+
+RC_WARN + 0x010
+
+the 1 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H1
+
+RC_WARN + 0x011
+
+the 2 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H2
+
+RC_WARN + 0x012
+
+the 3 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H3
+
+RC_WARN + 0x013
+
+the 4 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H4
+
+RC_WARN + 0x014
+
+the 5 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H5
+
+RC_WARN + 0x015
+
+the 6 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H6
+
+RC_WARN + 0x016
+
+the 7 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_S0
+
+RC_WARN + 0x018
+
+the 1 authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S1
+
+RC_WARN + 0x019
+
+the 2 authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S2
+
+RC_WARN + 0x01A
+
+the 3 authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S3
+
+RC_WARN + 0x01B
+
+the 4th authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S4
+
+RC_WARN + 0x01C
+
+the 5 session handle references a session that is
+not loaded
+
+TPM_RC_REFERENCE_S5
+
+RC_WARN + 0x01D
+
+the 6 session handle references a session that is
+not loaded
+
+st
+
+nd
+
+rd
+
+th
+
+th
+
+th
+
+th
+
+st
+
+nd
+
+rd
+
+th
+
+th
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 35
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Name
+
+Value
+
+Description
+
+TPM_RC_REFERENCE_S6
+
+RC_WARN + 0x01E
+
+the 7 authorization session handle references a
+session that is not loaded
+
+TPM_RC_NV_RATE
+
+RC_WARN + 0x020
+
+the TPM is rate-limiting accesses to prevent
+wearout of NV
+
+TPM_RC_LOCKOUT
+
+RC_WARN + 0x021
+
+authorizations for objects subject to DA protection
+are not allowed at this time because the TPM is in
+DA lockout mode
+
+TPM_RC_RETRY
+
+RC_WARN + 0x022
+
+the TPM was not able to start the command
+
+TPM_RC_NV_UNAVAILABLE
+
+RC_WARN + 0x023
+
+the command may require writing of NV and NV is
+not current accessible
+
+TPM_RC_NOT_USED
+
+RC_WARN + 0x7F
+
+this value is reserved and shall not be returned by
+the TPM
+
+th
+
+Additional Defines
+TPM_RC_H
+
+0x000
+
+add to a handle-related error
+
+TPM_RC_P
+
+0x040
+
+add to a parameter-related error
+
+TPM_RC_S
+
+0x800
+
+add to a session-related error
+
+TPM_RC_1
+
+0x100
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_2
+
+0x200
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_3
+
+0x300
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_4
+
+0x400
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_5
+
+0x500
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_6
+
+0x600
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_7
+
+0x700
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_8
+
+0x800
+
+add to a parameter-related error
+
+TPM_RC_9
+
+0x900
+
+add to a parameter-related error
+
+TPM_RC_A
+
+0xA00
+
+add to a parameter-related error
+
+TPM_RC_B
+
+0xB00
+
+add to a parameter-related error
+
+TPM_RC_C
+
+0xC00
+
+add to a parameter-related error
+
+TPM_RC_D
+
+0xD00
+
+add to a parameter-related error
+
+TPM_RC_E
+
+0xE00
+
+add to a parameter-related error
+
+TPM_RC_F
+
+0xF00
+
+add to a parameter-related error
+
+TPM_RC_N_MASK
+
+0xF00
+
+number mask
+
+Page 36
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.7
+
+Part 2: Structures
+
+TPM_CLOCK_ADJUST
+
+A TPM_CLOCK_ADJUST value is used to change the rate at which the TPM internal oscillator is divided.
+A change to the divider will change the rate at which Clock and Time change.
+NOTE
+
+The recommended adjustments are approximately 1% for a course adjustment, 0.1% for a medium
+adjustment, and the minimum possible on the implementation for the fine adjustment (e.g., one count of
+the pre-scalar if possible).
+
+Table 16 — Definition of (INT8) TPM_CLOCK_ADJUST Constants <IN>
+Name
+
+Value
+
+Comments
+
+TPM_CLOCK_COARSE_SLOWER
+
+-3
+
+Slow the Clock update rate by one coarse adjustment step.
+
+TPM_CLOCK_MEDIUM_SLOWER
+
+-2
+
+Slow the Clock update rate by one medium adjustment step.
+
+TPM_CLOCK_FINE_SLOWER
+
+-1
+
+Slow the Clock update rate by one fine adjustment step.
+
+TPM_CLOCK_NO_CHANGE
+
+0
+
+No change to the Clock update rate.
+
+TPM_CLOCK_FINE_FASTER
+
+1
+
+Speed the Clock update rate by one fine adjustment step.
+
+TPM_CLOCK_MEDIUM_FASTER
+
+2
+
+Speed the Clock update rate by one medium adjustment step.
+
+TPM_CLOCK_COARSE_FASTER
+
+3
+
+Speed the Clock update rate by one coarse adjustment step.
+
+#TPM_RC_VALUE
+
+6.8
+
+TPM_EO (EA Arithmetic Operands)
+Table 17 — Definition of (UINT16) TPM_EO Constants <IN/OUT>
+
+Operation Name
+
+Value
+
+Comments
+
+TPM_EO_EQ
+
+0x0000
+
+A=B
+
+TPM_EO_NEQ
+
+0x0001
+
+A≠B
+
+TPM_EO_SIGNED_GT
+
+0x0002
+
+A > B signed
+
+TPM_EO_UNSIGNED_GT
+
+0x0003
+
+A > B unsigned
+
+TPM_EO_SIGNED_LT
+
+0x0004
+
+A < B signed
+
+TPM_EO_UNSIGNED_LT
+
+0x0005
+
+A < B unsigned
+
+TPM_EO_SIGNED_GE
+
+0x0006
+
+A ≥ B signed
+
+TPM_EO_UNSIGNED_GE
+
+0x0007
+
+A ≥ B unsigned
+
+TPM_EO_SIGNED_LE
+
+0x0008
+
+A ≤ B signed
+
+TPM_EO_UNSIGNED_LE
+
+0x0009
+
+A ≤ B unsigned
+
+TPM_EO_BITSET
+
+0x000A
+
+All bits SET in B are SET in A. ((A&B)=B)
+
+TPM_EO_BITCLEAR
+
+0x000B
+
+All bits SET in B are CLEAR in A. ((A&B)=0)
+
+#TPM_RC_VALUE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Response code returned when unmarshaling of this type fails
+
+Published
+Copyright © TCG 2006-2013
+
+Page 37
+October 31, 2013
+
+ Part 2: Structures
+
+6.9
+
+Trusted Platform Module Library
+
+TPM_ST (Structure Tags)
+
+Structure tags are used to disambiguate structures. They are 16-bit values with the most significant bit
+SET so that they do not overlap TPM_ALG_ID values. A single exception is made for the value
+associated with TPM_ST_RSP_COMMAND (0x00C4), which has the same value as the
+TPM_TAG_RSP_COMMAND tag from earlier versions of this specification. This value is used when the
+TPM is compatible with a previous TPM specification and the TPM cannot determine which family of
+response code to return because the command tag is not valid.
+Many of the structures defined in this document have parameters that are unions of other structures. That
+is, a parameter may be one of several structures. The parameter will have a selector value that indicates
+which of the options is actually present.
+In order to allow the marshaling and unmarshaling code to determine which of the possible structures is
+allowed, each selector will have a unique interface type and will constrain the number of possible tag
+values.
+Table 18 defines the structure tags values. The definition of many structures is context-sensitive using an
+algorithm ID. In cases where an algorithm ID is not a meaningful way to designate the structure, the
+values in this table are used.
+Table 18 — Definition of (UINT16) TPM_ST Constants <IN/OUT, S>
+Name
+TPM_ST_RSP_COMMAND
+
+Value
+
+Comments
+
+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
+TPM_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,
+TPM_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.
+
+TPM_ST_NULL
+
+0X8000
+
+no structure type specified
+
+TPM_ST_NO_SESSIONS
+
+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
+authorizationSize/parameterSize value is present
+If the responseCode from the TPM is not
+TPM_RC_SUCCESS, then the response tag shall
+have this value.
+
+TPM_ST_SESSIONS
+
+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 authorizationSize/parameterSize
+field is present
+
+Page 38
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Name
+reserved
+
+Part 2: Structures
+Value
+
+Comments
+
+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 TPM_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
+
+reserved
+
+0x8004
+
+This tag is not used by all TPM or TRM
+implementations.
+
+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 TPM_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.
+
+TPM_ST_ATTEST_NV
+
+0x8014
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_COMMAND_AUDIT
+
+0x8015
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_SESSION_AUDIT
+
+0x8016
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_CERTIFY
+
+0x8017
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_QUOTE
+
+0x8018
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_TIME
+
+0x8019
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_CREATION
+
+0x801A
+
+tag for an attestation structure
+
+reserved
+
+0x801B
+
+do not use
+NOTE
+
+This
+was
+previously
+assigned
+to
+TPM_ST_ATTEST_NV. The tag is changed
+because the structure has changed
+
+TPM_ST_CREATION
+
+0x8021
+
+tag for a ticket type
+
+TPM_ST_VERIFIED
+
+0x8022
+
+tag for a ticket type
+
+TPM_ST_AUTH_SECRET
+
+0x8023
+
+tag for a ticket type
+
+TPM_ST_HASHCHECK
+
+0x8024
+
+tag for a ticket type
+
+TPM_ST_AUTH_SIGNED
+
+0x8025
+
+tag for a ticket type
+
+TPM_ST_FU_MANIFEST
+
+0x8029
+
+tag for a structure describing a Field Upgrade Policy
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 39
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+6.10 TPM_SU (Startup Type)
+These values are used in TPM2_Startup() to indicate the shutdown and startup mode. The defined
+startup sequences are:
+a) TPM Reset – Two cases:
+1) Shutdown(CLEAR) followed by Startup(CLEAR)
+2) Startup(CLEAR) with no Shutdown()
+b) TPM Restart – Shutdown(STATE) followed by Startup(CLEAR)
+c) TPM Resume – Shutdown(STATE) followed by Startup(STATE)
+TPM_SU values of 80 0016 and above are reserved for internal use of the TPM and may not be assigned
+values.
+NOTE
+
+In the reference code, a value of FF FF 16 indicates that the startup state has not been set. If this was
+defined in this table to be, say, TPM_SU_NONE, then TPM_SU_NONE would be a valid input value but
+the caller is not allowed to indicate the that the startup type is TPM_SU_NONE so the reserved value is
+defined in the implementation as required for internal TPM uses.
+
+Table 19 — Definition of (UINT16) TPM_SU Constants <IN>
+Name
+
+Value
+
+Description
+
+TPM_SU_CLEAR
+
+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 start from
+perform TPM Reset or TPM Restart
+
+TPM_SU_STATE
+
+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(TPM_SU_STATE)
+
+#TPM_RC_VALUE
+
+response code when incorrect value is used
+
+6.11 TPM_SE (Session Type)
+This type is used in TPM2_StartAuthSession() to indicate the type of the session to be created.
+Table 20 — Definition of (UINT8) TPM_SE Constants <IN>
+Name
+
+Value
+
+TPM_SE_HMAC
+
+0x00
+
+TPM_SE_POLICY
+
+0x01
+
+TPM_SE_TRIAL
+
+0x03
+
+#TPM_RC_VALUE
+
+Page 40
+October 31, 2013
+
+Description
+
+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.
+response code when incorrect value is used
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+6.12 TPM_CAP (Capabilities)
+The TPM_CAP values are used in TPM2_GetCapability() to select the type of the value to be returned.
+The format of the response varies according to the type of the value.
+Table 21 — Definition of (UINT32) TPM_CAP Constants
+Capability Name
+
+Value
+
+Property Type
+
+Return Type
+
+TPM_CAP_FIRST
+
+0x00000000
+
+TPM_CAP_ALGS
+
+0x00000000 TPM_ALG_ID
+
+TPM_CAP_HANDLES
+
+0x00000001 TPM_HANDLE
+
+TPML_HANDLE
+
+TPM_CAP_COMMANDS
+
+0x00000002 TPM_CC
+
+TPML_CCA
+
+TPM_CAP_PP_COMMANDS
+
+0x00000003 TPM_CC
+
+TPML_CC
+
+TPM_CAP_AUDIT_COMMANDS
+
+0x00000004 TPM_CC
+
+TPML_CC
+
+TPM_CAP_PCRS
+
+0x00000005 reserved
+
+TPML_PCR_SELECTION
+
+TPM_CAP_TPM_PROPERTIES
+
+0x00000006 TPM_PT
+
+TPML_TAGGED_TPM_PROPERTY
+
+TPM_CAP_PCR_PROPERTIES
+
+0x00000007 TPM_PT_PCR
+
+(1)
+
+TPM_CAP_ECC_CURVES
+
+0x00000008 TPM_ECC_CURVE
+
+TPM_CAP_LAST
+
+TPML_ALG_PROPERTY
+
+TPML_TAGGED_PCR_PROPERTY
+(1)
+
+0x00000008
+
+TPM_CAP_VENDOR_PROPERTY 0x00000100 manufacturer specific
+
+TPML_ECC_CURVE
+
+manufacturer-specific values
+
+#TPM_RC_VALUE
+NOTES:
+(1) The TPM_ALG_ID or TPM_ECC_CURVE is cast to a UINT32
+
+6.13 TPM_PT (Property Tag)
+The TPM_PT constants are used in TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES) to
+indicate the property being selected or returned.
+The values in the fixed group (PT_FIXED) are not changeable through programmatic means other than a
+firmware update. The values in the variable group (PT_VAR) may be changed with TPM commands but
+should be persistent over power cycles and only changed when indicated by the detailed actions code.
+Table 22 — Definition of (UINT32) TPM_PT Constants <IN/OUT, S>
+Capability Name
+
+Value
+
+Comments
+
+TPM_PT_NONE
+
+0x00000000
+
+indicates no property type
+
+PT_GROUP
+
+0x00000100
+
+The number of properties in each group.
+NOTE The first group with any properties is group 1
+(PT_GROUP * 1). Group 0 is reserved.
+
+PT_FIXED
+
+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.
+
+TPM_PT_FAMILY_INDICATOR
+
+PT_FIXED + 0 a 4-octet character string containing the TPM Family value
+(TPM_SPEC_FAMILY)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 41
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+TPM_PT_LEVEL
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+PT_FIXED + 1 the level of the specification
+NOTE 1
+
+TPM_PT_REVISION
+
+For this specification, the level is zero.
+
+NOTE 2
+
+The level is on the title page of the specification.
+
+PT_FIXED + 2 the specification Revision times 100
+EXAMPLE Revision 01.01 would have a value of 101.
+NOTE
+
+TPM_PT_DAY_OF_YEAR
+
+The Revision value is on the title page of the
+specification.
+
+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
+
+TPM_PT_YEAR
+
+The specification date is on the title page of the
+specification.
+
+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.
+
+TPM_PT_MANUFACTURER
+
+PT_FIXED + 5 the vendor ID unique to each TPM manufacturer
+
+TPM_PT_VENDOR_STRING_1
+
+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.
+
+TPM_PT_VENDOR_STRING_2
+
+PT_FIXED + 7 the second four characters of the vendor ID string
+
+TPM_PT_VENDOR_STRING_3
+
+PT_FIXED + 8 the third four characters of the vendor ID string
+
+TPM_PT_VENDOR_STRING_4
+
+PT_FIXED + 9 the fourth four characters of the vendor ID sting
+
+TPM_PT_VENDOR_TPM_TYPE
+
+PT_FIXED + 10 vendor-defined value indicating the TPM model
+
+TPM_PT_FIRMWARE_VERSION_1
+
+PT_FIXED + 11 the most-significant 32 bits of a vendor-specific value
+indicating the version of the firmware
+
+TPM_PT_FIRMWARE_VERSION_2
+
+PT_FIXED + 12 the least-significant 32 bits of a vendor-specific value
+indicating the version of the firmware
+
+TPM_PT_INPUT_BUFFER
+
+PT_FIXED + 13 the maximum size of
+TPM2B_MAX_BUFFER)
+
+TPM_PT_HR_TRANSIENT_MIN
+
+PT_FIXED + 14 the minimum number of transient objects that can be held
+in TPM RAM
+NOTE
+
+TPM_PT_HR_PERSISTENT_MIN
+
+parameter
+
+(typically,
+
+a
+
+This minimum shall be no less than the minimum
+value required by the platform-specific specification
+to which the TPM is built.
+
+PT_FIXED + 15 the minimum number of persistent objects that can be
+held in TPM NV memory
+NOTE
+
+TPM_PT_HR_LOADED_MIN
+
+a
+
+This minimum shall be no less than the minimum
+value required by the platform-specific specification
+to which the TPM is built.
+
+PT_FIXED + 16 the minimum number of authorization sessions that can
+be held in TPM RAM
+NOTE
+
+Page 42
+October 31, 2013
+
+This minimum shall be no less than the minimum
+value required by the platform-specific specification
+to which the TPM is built.
+
+Published
+
+Family “2.0”
+
+Copyright © TCG 2006-2013
+
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Capability Name
+TPM_PT_ACTIVE_SESSIONS_MAX
+
+Part 2: Structures
+Value
+
+Comments
+
+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.
+
+TPM_PT_PCR_COUNT
+
+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.
+
+TPM_PT_PCR_SELECT_MIN
+
+PT_FIXED + 19 the
+minimum
+number
+of
+TPMS_PCR_SELECT.sizeOfSelect
+NOTE
+
+TPM_PT_CONTEXT_GAP_MAX
+
+octets
+
+in
+
+a
+
+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.
+
+PT_FIXED + 20 the maximum allowed difference (unsigned) between the
+contextID values of two saved session contexts
+16
+
+This value shall be at least 2 -1 (65535).
+PT_FIXED + 21 skipped
+TPM_PT_NV_COUNTERS_MAX
+
+PT_FIXED + 22 the maximum number of NV Indexes that are allowed to
+have the TPMA_NV_COUNTER attribute SET
+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.
+
+TPM_PT_NV_INDEX_MAX
+
+PT_FIXED + 23 the maximum size of an NV Index data area
+
+TPM_PT_MEMORY
+
+PT_FIXED + 24 a TPMA_MEMORY indicating the memory management
+method for the TPM
+
+TPM_PT_CLOCK_UPDATE
+
+PT_FIXED + 25 interval, in milliseconds, between updates to the copy of
+TPMS_CLOCK_INFO.clock in NV
+
+TPM_PT_CONTEXT_HASH
+
+PT_FIXED + 26 the algorithm used for the integrity HMAC on saved
+contexts
+and
+for
+hashing
+the
+fuData
+of
+TPM2_FirmwareRead()
+
+TPM_PT_CONTEXT_SYM
+
+PT_FIXED + 27 the algorithm used for encryption of saved contexts
+
+TPM_PT_CONTEXT_SYM_SIZE
+
+PT_FIXED + 28 the size of the key used for encryption of saved contexts
+
+TPM_PT_ORDERLY_COUNT
+
+PT_FIXED + 29 the modulus - 1 of the count for NV update of an orderly
+counter
+The returned value is MAX_ORDERLY_COUNT.
+N
+This will have a value of 2 – 1 where 1 ≤ N ≤ 32
+NOTE
+
+An “orderly counter” is an NV Index with
+TPMA_NV_COUNTER and TPMA_NV_ORDERLY
+both SET.
+
+TPM_PT_MAX_COMMAND_SIZE
+
+PT_FIXED + 30 the maximum value for commandSize in a command
+
+TPM_PT_MAX_RESPONSE_SIZE
+
+PT_FIXED + 31 the maximum value for responseSize in a response
+
+TPM_PT_MAX_DIGEST
+
+PT_FIXED + 32 the maximum size of a digest that can be produced by the
+TPM
+
+TPM_PT_MAX_OBJECT_CONTEXT
+
+PT_FIXED + 33 the maximum size of an object context that will be
+returned by TPM2_ContextSave
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 43
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+TPM_PT_MAX_SESSION_CONTEXT PT_FIXED + 34 the maximum size of a session context that will be
+returned by TPM2_ContextSave
+TPM_PT_PS_FAMILY_INDICATOR
+
+PT_FIXED + 35 platform-specific family (a TPM_PS value)(see Table 24)
+NOTE
+
+The platform-specific values for the TPM_PT_PS
+parameters are in the relevant platform-specific
+specification. In the reference implementation, all of
+these values are 0.
+
+TPM_PT_PS_LEVEL
+
+PT_FIXED + 36 the level of the platform-specific specification
+
+TPM_PT_PS_REVISION
+
+PT_FIXED + 37 the specification Revision times 100 for the platformspecific specification
+
+TPM_PT_PS_DAY_OF_YEAR
+
+PT_FIXED + 38 the platform-specific specification day of year using TCG
+calendar
+
+TPM_PT_PS_YEAR
+
+PT_FIXED + 39 the platform-specific specification year using the CE
+
+TPM_PT_SPLIT_MAX
+
+PT_FIXED + 40 the number of split signing operations supported by the
+TPM
+
+TPM_PT_TOTAL_COMMANDS
+
+PT_FIXED + 41 total number of commands implemented in the TPM
+
+TPM_PT_LIBRARY_COMMANDS
+
+PT_FIXED + 42 number of commands from the TPM library that are
+implemented
+
+TPM_PT_VENDOR_COMMANDS
+
+PT_FIXED + 43 number of vendor commands that are implemented
+
+TPM_PT_NV_BUFFER_MAX
+
+PT_FIXED + 44 the maximum data size in one NV write command
+
+PT_VAR
+
+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.
+
+TPM_PT_PERMANENT
+
+PT_VAR + 0
+
+TPMA_PERMANENT
+
+TPM_PT_STARTUP_CLEAR
+
+PT_VAR + 1
+
+TPMA_STARTUP_CLEAR
+
+TPM_PT_HR_NV_INDEX
+
+PT_VAR + 2
+
+the number of NV Indexes currently defined
+
+TPM_PT_HR_LOADED
+
+PT_VAR + 3
+
+the number of authorization sessions currently loaded into
+TPM RAM
+
+TPM_PT_HR_LOADED_AVAIL
+
+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
+
+TPM_PT_HR_ACTIVE
+
+Page 44
+October 31, 2013
+
+PT_VAR + 5
+
+A valid implementation may return 1 even if more
+than one authorization session would fit into RAM.
+
+the number of active authorization sessions currently
+being tracked by the TPM
+This is the sum of the loaded and saved sessions.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Capability Name
+TPM_PT_HR_ACTIVE_AVAIL
+
+Part 2: Structures
+Value
+
+Comments
+
+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
+
+TPM_PT_HR_TRANSIENT_AVAIL
+
+PT_VAR + 7
+
+A valid implementation may return 1 even if more
+than one authorization session could be created.
+
+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.
+
+TPM_PT_HR_PERSISTENT
+
+PT_VAR + 8
+
+the number of persistent objects currently loaded into
+TPM NV memory
+
+TPM_PT_HR_PERSISTENT_AVAIL
+
+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.
+
+TPM_PT_NV_COUNTERS
+
+PT_VAR + 10
+
+the number of defined NV Indexes that have NV
+TPMA_NV_COUNTER attribute SET
+
+TPM_PT_NV_COUNTERS_AVAIL
+
+PT_VAR + 11
+
+the number of additional NV Indexes that can be defined
+with
+their
+TPMA_NV_COUNTER
+and
+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 the
+TPMA_NV_COUNTER
+and
+TPMA_NV_ORDERLY
+attributes SET. 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.
+
+TPM_PT_ALGORITHM_SET
+
+PT_VAR + 12
+
+code that limits the algorithms that may be used with the
+TPM
+
+TPM_PT_LOADED_CURVES
+
+PT_VAR + 13
+
+the number of loaded ECC curves
+
+TPM_PT_LOCKOUT_COUNTER
+
+PT_VAR + 14
+
+the current value of the lockout counter (failedTries)
+
+TPM_PT_MAX_AUTH_FAIL
+
+PT_VAR + 15
+
+the number of authorization failures before DA lockout is
+invoked
+
+TPM_PT_LOCKOUT_INTERVAL
+
+PT_VAR + 16
+
+the number of seconds before the value reported by
+TPM_PT_LOCKOUT_COUNTER is decremented
+
+TPM_PT_LOCKOUT_RECOVERY
+
+PT_VAR + 17
+
+the number of seconds after a lockoutAuth failure before
+use of lockoutAuth may be attempted again
+
+TPM_PT_NV_WRITE_RECOVERY
+
+PT_VAR + 18
+
+number of milliseconds before the TPM will accept
+another command that will modify NV
+This value is an approximation and may go up or down
+over time.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 45
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+TPM_PT_AUDIT_COUNTER_0
+
+PT_VAR + 19
+
+the high-order 32 bits of the command audit counter
+
+TPM_PT_AUDIT_COUNTER_1
+
+PT_VAR + 20
+
+the low-order 32 bits of the command audit counter
+
+Page 46
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+6.14 TPM_PT_PCR (PCR Property Tag)
+The TPM_PT_PCR constants are used in TPM2_GetCapability() to indicate the property being selected
+or returned. The PCR properties can be read when capability == TPM_CAP_PCR_PROPERTIES.
+Table 23 — Definition of (UINT32) TPM_PT_PCR Constants <IN/OUT, S>
+Capability Name
+
+Value
+
+Comments
+
+TPM_PT_PCR_FIRST
+
+0x00000000
+
+bottom of the range of TPM_PT_PCR properties
+
+TPM_PT_PCR_SAVE
+
+0x00000000
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR is
+saved and restored by TPM_SU_STATE
+
+TPM_PT_PCR_EXTEND_L0
+
+0x00000001
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be extended from locality 0
+This property is only present if a locality other than 0 is
+implemented.
+
+TPM_PT_PCR_RESET_L0
+
+0x00000002
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 0
+
+TPM_PT_PCR_EXTEND_L1
+
+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.
+
+TPM_PT_PCR_RESET_L1
+
+0x00000004
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 1
+This property is only present if locality 1 is implemented.
+
+TPM_PT_PCR_EXTEND_L2
+
+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.
+
+TPM_PT_PCR_RESET_L2
+
+0x00000006
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 2
+This property is only present if localities 1 and 2 are
+implemented.
+
+TPM_PT_PCR_EXTEND_L3
+
+0x00000007
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be extended from locality 3
+This property is only present if localities 1, 2, and 3 are
+implemented.
+
+TPM_PT_PCR_RESET_L3
+
+0x00000008
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 3
+This property is only present if localities 1, 2, and 3 are
+implemented.
+
+TPM_PT_PCR_EXTEND_L4
+
+0x00000009
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be extended from locality 4
+This property is only present if localities 1, 2, 3, and 4 are
+implemented.
+
+TPM_PT_PCR_RESET_L4
+
+0x0000000A
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 4
+This property is only present if localities 1, 2, 3, and 4 are
+implemented.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 47
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+reserved
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+0x0000000B – the values in this range are reserved
+0x00000010 They correspond to values that may be used to describe
+attributes associated with the extended localities (32255).synthesize additional software localities. The meaning of
+these properties need not be the same as the meaning for the
+Extend and Reset properties above.
+
+TPM_PT_PCR_NO_INCREMENT
+
+0x00000011
+
+a SET bit in the TPMS_PCR_SELECT indicates that
+modifications to this PCR (reset or Extend) will not increment
+the pcrUpdateCounter
+
+TPM_PT_PCR_DRTM_RESET
+
+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.
+
+TPM_PT_PCR_POLICY
+
+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.
+
+TPM_PT_PCR_AUTH
+
+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.
+
+reserved
+
+0x00000015
+
+reserved for the next (2 ) TPM_PT_PCR_POLICY set
+
+reserved
+
+0x00000016
+
+reserved for the next (2 ) TPM_PT_PCR_AUTH set
+
+reserved
+
+nd
+nd
+
+nd
+
+th
+
+0x00000017 – reserved for the 2 through 255 TPM_PT_PCR_POLICY and
+0x00000210 TPM_PT_PCR_AUTH values
+th
+
+and
+
+highest
+
+allowed,
+
+th
+
+and
+
+highest
+
+allowed,
+
+reserved
+
+0x00000211
+
+reserved
+to
+the
+256 ,
+TPM_PT_PCR_POLICY set
+
+reserved
+
+0x00000212
+
+reserved
+to
+the
+256 ,
+TPM_PT_PCR_AUTH set
+
+reserved
+
+0x00000213
+
+new PCR property values may be assigned starting with this
+value
+
+TPM_PT_PCR_LAST
+
+0x00000014
+
+top of the range of TPM_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
+
+Page 48
+October 31, 2013
+
+This is an implementation-specific value. The value shown
+reflects the reference code implementation.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+6.15 TPM_PS (Platform Specific)
+The platform values in Table 24 are used for the TPM_PT_PS_FAMILY_INDICATOR.
+NOTE
+
+Values below six (6) have the same values as the purview assignments in TPM 1.2.
+
+Table 24 — Definition of (UINT32) TPM_PS Constants <OUT>
+Capability Name
+
+Value
+
+Comments
+
+TPM_PS_MAIN
+
+0x00000000
+
+not platform specific
+
+TPM_PS_PC
+
+0x00000001
+
+PC Client
+
+TPM_PS_PDA
+
+0x00000002
+
+PDA (includes all mobile devices that are not specifically cell
+phones)
+
+TPM_PS_CELL_PHONE
+
+0x00000003
+
+Cell Phone
+
+TPM_PS_SERVER
+
+0x00000004
+
+Server WG
+
+TPM_PS_PERIPHERAL
+
+0x00000005
+
+Peripheral WG
+
+TPM_PS_TSS
+
+0x00000006
+
+TSS WG
+
+TPM_PS_STORAGE
+
+0x00000007
+
+Storage WG
+
+TPM_PS_AUTHENTICATION
+
+0x00000008
+
+Authentication WG
+
+TPM_PS_EMBEDDED
+
+0x00000009
+
+Embedded WG
+
+TPM_PS_HARDCOPY
+
+0x0000000A
+
+Hardcopy WG
+
+TPM_PS_INFRASTRUCTURE
+
+0x0000000B
+
+Infrastructure WG
+
+TPM_PS_VIRTUALIZATION
+
+0x0000000C Virtualization WG
+
+TPM_PS_TNC
+
+0x0000000D Trusted Network Connect WG
+
+TPM_PS_MULTI_TENANT
+
+0x0000000E
+
+Multi-tenant WG
+
+TPM_PS_TC
+
+0x0000000F
+
+Technical Committee
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 49
+October 31, 2013
+
+ Part 2: Structures
+
+7
+
+Trusted Platform Module Library
+
+Handles
+
+7.1
+
+Introduction
+
+Handles are 32-bit values used to reference shielded locations of various types within the TPM.
+Table 25 — Definition of Types for Handles
+Type
+
+Name
+
+Description
+
+UINT32
+
+TPM_HANDLE
+
+Handles may refer to objects (keys or data blobs), authorization sessions (HMAC and policy), NV
+Indexes, permanent TPM locations, and PCR.
+7.2
+
+TPM_HT (Handle Types)
+
+The 32-bit handle space is divided into 256 regions of equal size with 2
+ranges represents a handle type.
+
+24
+
+values in each. Each of these
+
+The type of the entity is indicated by the MSO of its handle. The values for the MSO and the entity
+referenced are shown in Table 26.
+Table 26 — Definition of (UINT8) TPM_HT Constants <S>
+Name
+
+Value
+
+Comments
+
+TPM_HT_PCR
+
+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.
+
+TPM_HT_NV_INDEX
+
+0x01
+
+NV Index – assigned by the caller
+
+TPM_HT_HMAC_SESSION
+
+0x02
+
+HMAC Authorization Session – assigned by the TPM when the
+session is created
+
+TPM_HT_LOADED_SESSION
+
+0x02
+
+Loaded Authorization Session – used only in the context of
+TPM2_GetCapability
+This type references both loaded HMAC and loaded policy
+authorization sessions.
+
+TPM_HT_POLICY_SESSION
+
+0x03
+
+Policy Authorization Session – assigned by the TPM when the
+session is created
+
+TPM_HT_ACTIVE_SESSION
+
+0x03
+
+Active 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.
+
+TPM_HT_PERMANENT
+
+0x40
+
+Permanent Values – assigned by this specification in Table 27
+
+TPM_HT_TRANSIENT
+
+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
+
+TPM_HT_PERSISTENT
+
+0x81
+
+Persistent Objects – assigned by the TPM when a loaded transient
+object is made persistent
+
+Page 50
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+When a transient object is loaded, the TPM shall assign a handle with an MSO of TPM_HT_TRANSIENT.
+The object may be assigned a different handle each time it is loaded. The TPM shall ensure that handles
+assigned to transient objects are unique and assigned to only one transient object at a time.
+EXAMPLE
+
+If a TPM is only able to hold 4 transient objects in internal memory, it might choose to assign handles to
+those objects with the values 80 00 00 0016 – 80 00 00 0316.
+
+When a transient object is converted to a persistent object (TPM2_EvictControl()), the TPM shall validate
+that the handle provided by the caller has an MSO of TPM_HT_PERSISTENT and that the handle is not
+already assigned to a persistent object.
+A handle is assigned to a session when the session is started. The handle shall have an MSO equal to
+TPM_HT_SESSION and remain associated with that session until the session is closed or flushed. The
+TPM shall ensure that a session handle is only associated with one session at a time. When the session
+is loaded into the TPM using TPM2_LoadContext(), it will have the same handle each time it is loaded.
+EXAMPLE
+
+7.3
+
+If a TPM is only able to track 64 active sessions at a time, it could number those sessions using the
+values xx 00 01 0016 – xx 00 01 3F 16 where xx is either 02 16 or 03 16 depending on the session type.
+
+Persistent Handle Sub-ranges
+
+Persistent handles are assigned by the caller of TPM2_EvictControl(). ownerAuth or platformAuth is
+required to authorize allocation of space for a persistent object. These entities are given separate ranges
+of persistent handles so that they do not have to allocate from a common range of handles.
+NOTE
+
+While this “namespace” allocation of the handle ranges could have been handled by convention, TPM
+enforcement is used to prevent errors by the OS or malicious software from affecting the platform’s use of
+the NV memory.
+
+The Owner is allocated persistent handles in the range of 81 00 00 0016 to 81 7F FF FF16 inclusive and
+the TPM will return an error if ownerAuth is used to attempt to assign a persistent handle outside of this
+range.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 51
+October 31, 2013
+
+ Part 2: Structures
+7.4
+
+Trusted Platform Module Library
+
+TPM_RH (Permanent Handles)
+
+Table 27 lists the architecturally defined handles that cannot be changed. The handles include
+authorization handles, and special handles.
+Table 27 — Definition of (UINT32) TPM_RH Constants <IN, S>
+Name
+
+Value
+
+Type
+
+TPM_RH_FIRST
+
+0x40000000
+
+R
+
+TPM_RH_SRK
+
+0x40000000
+
+R
+
+TPM_RH_OWNER
+
+0x40000001
+
+K, A, P
+
+TPM_RH_REVOKE
+
+0x40000002
+
+R
+
+not used
+
+1
+
+TPM_RH_TRANSPORT
+
+0x40000003
+
+R
+
+not used
+
+1
+
+TPM_RH_OPERATOR
+
+0x40000004
+
+R
+
+not used
+
+1
+
+TPM_RH_ADMIN
+
+0x40000005
+
+R
+
+not used
+
+1
+
+TPM_RH_EK
+
+0x40000006
+
+R
+
+not used
+
+1
+
+TPM_RH_NULL
+
+0x40000007
+
+K, A, P
+
+a handle associated with the null hierarchy, an EmptyAuth
+authValue, and an Empty Policy authPolicy.
+
+TPM_RH_UNASSIGNED
+
+0x40000008
+
+R
+
+value reserved to the TPM to indicate a handle location that
+has not been initialized or assigned
+
+TPM_RS_PW
+
+0x40000009
+
+S
+
+authorization value
+authorization session
+
+TPM_RH_LOCKOUT
+
+0x4000000A
+
+A
+
+references the authorization associated with the dictionary
+attack lockout reset
+
+TPM_RH_ENDORSEMENT
+
+0x4000000B
+
+K, A, P
+
+references the Endorsement Primary
+endorsementAuth, and endorsementPolicy
+
+TPM_RH_PLATFORM
+
+0x4000000C
+
+K, A, P
+
+references the Platform Primary Seed (PPS), platformAuth,
+and platformPolicy
+
+TPM_RH_PLATFORM_NV
+
+0x4000000D
+
+C
+
+for phEnableNV
+
+R
+
+the top of the reserved handle area
+This is set to allow TPM2_GetCapability() to know where to
+stop. It may vary as implementations add to the permanent
+handle area.
+
+TPM_RH_LAST
+
+0x4000000D
+
+Comments
+
+not used
+
+1
+
+handle references the Storage Primary Seed (SPS), the
+ownerAuth, and the ownerPolicy
+
+used
+
+to
+
+indicate
+
+a
+
+password
+
+Seed
+
+(EPS),
+
+Type definitions:
+R – a reserved value
+K – a Primary Seed
+A – an authorization value
+P – a policy value
+S – a session handle
+C - a controlNote 1 The handle is only used in a TPM that is compatible with a previous version of this specification. It is not used
+in any command defined in this version of the specification.
+
+Page 52
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+7.5
+
+Part 2: Structures
+
+TPM_HC (Handle Value Constants)
+
+The definitions in Table 28 are used to define many of the interface data types. However, the values of
+these constants, other than PCR_FIRST, are informative and may be changed by an implementation as
+long as the values stay within the prescribed ranges for the handle type.
+NOTE
+
+PCR0 is architecturally defined to have a handle value of 0.
+
+For the reference implementation, the handle range for sessions starts at the lowest allowed value for a
+session handle. The highest value for a session handle is determined by how many active sessions are
+allowed by the implementation. The MSO of the session handle will be set according to the session type.
+A similar approach is used for transient objects with the first assigned handle at the bottom of the range
+defined by TPM_HT_TRANSIENT and the top of the range determined by the implementation-dependent
+value of MAX_LOADED_OBJECTS.
+The first assigned handle for evict objects is also at the bottom of the allowed range defined by
+TPM_HT_PERSISTENT and the top of the range determined by the implementation-dependent value of
+MAX_EVICT_OBJECTS.
+NOTE
+
+The values in Table 28 are intended to facilitate the process of making the handle larger than 32 bits in
+the future. It is intended that HR_MASK and HR_SHIFT are the only values that need change to resize
+the handle space.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 53
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Table 28 — Definition of (TPM_HANDLE) TPM_HC Constants <IN, S>
+Name
+
+Value
+
+Comments
+
+HR_HANDLE_MASK
+
+0x00FFFFFF
+
+to mask off the HR
+
+HR_RANGE_MASK
+
+0xFF000000
+
+to mask off the variable
+part
+
+HR_SHIFT
+
+24
+
+HR_PCR
+
+(TPM_HT_PCR << HR_SHIFT)
+
+HR_HMAC_SESSION
+
+(TPM_HT_HMAC_SESSION << HR_SHIFT)
+
+HR_POLICY_SESSION
+
+(TPM_HT_POLICY_SESSION << HR_SHIFT)
+
+HR_TRANSIENT
+
+(TPM_HT_TRANSIENT << HR_SHIFT)
+
+HR_PERSISTENT
+
+(TPM_HT_PERSISTENT << HR_SHIFT)
+
+HR_NV_INDEX
+
+(TPM_HT_NV_INDEX << HR_SHIFT)
+
+HR_PERMANENT
+
+(TPM_HT_PERMANENT << HR_SHIFT)
+
+PCR_FIRST
+
+(HR_PCR + 0)
+
+first PCR
+
+PCR_LAST
+
+(PCR_FIRST + IMPLEMENTATION_PCR-1)
+
+last PCR
+
+HMAC_SESSION_FIRST
+
+(HR_HMAC_SESSION + 0)
+
+first HMAC session
+
+HMAC_SESSION_LAST
+
+(HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1)
+
+last HMAC session
+
+LOADED_SESSION_FIRST HMAC_SESSION_FIRST
+
+used in GetCapability
+
+LOADED_SESSION_LAST
+
+HMAC_SESSION_LAST
+
+used in GetCapability
+
+POLICY_SESSION_FIRST
+
+(HR_POLICY_SESSION + 0)
+
+first policy session
+
+POLICY_SESSION_LAST
+
+(POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1) last policy session
+
+TRANSIENT_FIRST
+
+(HR_TRANSIENT + 0)
+
+first transient object
+
+ACTIVE_SESSION_FIRST
+
+POLICY_SESSION_FIRST
+
+used in GetCapability
+
+ACTIVE_SESSION_LAST
+
+POLICY_SESSION_LAST
+
+used in GetCapability
+
+TRANSIENT_LAST
+
+(TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1)
+
+last transient object
+
+PERSISTENT_FIRST
+
+(HR_PERSISTENT + 0)
+
+first persistent object
+
+PERSISTENT_LAST
+
+(PERSISTENT_FIRST + 0x00FFFFFF)
+
+last persistent object
+
+PLATFORM_PERSISTENT
+
+(PERSISTENT_FIRST + 0x00800000)
+
+first platform persistent
+object
+
+NV_INDEX_FIRST
+
+(HR_NV_INDEX + 0)
+
+first allowed NV Index
+
+NV_INDEX_LAST
+
+(NV_INDEX_FIRST + 0x00FFFFFF)
+
+last allowed NV Index
+
+PERMANENT_FIRST
+
+TPM_RH_FIRST
+
+PERMANENT_LAST
+
+TPM_RH_LAST
+
+Page 54
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Attribute Structures
+
+8
+8.1
+
+Description
+
+Attributes are expressed as bit fields of varying size. An attribute field structure may be 1, 2, or 4 octets in
+length.
+The bit numbers for an attribute structure are assigned with the number 0 assigned to the least-significant
+bit of the structure and the highest number assigned to the most-significant bit of the structure.
+The least significant bit is determined by treating the attribute structure as an integer. The least-significant
+bit would be the bit that is set when the value of the integer is 1.
+When any reserved bit in an attribute is SET, the TPM shall return TPM_RC_RESERVED_BITS. This
+response code is not shown in the tables for attributes.
+8.2
+
+TPMA_ALGORITHM
+
+This structure defines the attributes of an algorithm.
+Each algorithm has a fundamental attribute: asymmetric, symmetric, or hash. In some cases (e.g.,
+TPM_ALG_RSA or TPM_ALG_AES), this is the only attribute.
+A mode, method, or scheme may have an associated asymmetric, symmetric, or hash algorithm.
+Table 29 — Definition of (UINT32) TPMA_ALGORITHM Bits
+Bit
+
+Name
+
+Definition
+
+0
+
+asymmetric
+
+SET (1): an asymmetric algorithm with public and private portions
+CLEAR (0): not an asymmetric algorithm
+
+1
+
+symmetric
+
+SET (1): a symmetric block cipher
+CLEAR (0): not a symmetric block cipher
+
+2
+
+hash
+
+SET (1): a hash algorithm
+CLEAR (0): not a hash algorithm
+
+3
+
+object
+
+SET (1): an algorithm that may be used as an object type
+CLEAR (0): an algorithm that is not used as an object type
+
+7:4
+
+Reserved
+
+8
+
+signing
+
+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
+
+9
+
+encrypting
+
+SET (1): an encryption/decryption algorithm. The setting of asymmetric,
+symmetric, and hash will indicate the type of encryption/decryption algorithm.
+CLEAR (0): not an encryption/decryption algorithm
+
+10
+
+method
+
+SET (1): a method such as a key derivative function (KDF)
+CLEAR (0): not a method
+
+31:11 Reserved
+
+8.3
+8.3.1
+
+TPMA_OBJECT (Object Attributes)
+Introduction
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 55
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+This attribute structure indicates an object’s use, its authorization types, and it relationship to other
+objects.
+The state of the attributes is determined when the object is created and they are never changed by the
+TPM. Additionally, the setting of these structures is reflected in the integrity value of the private area of an
+object in order to allow the TPM to detect modifications of the Protected Object when stored off the TPM.
+8.3.2
+
+Structure Definition
+Table 30 — Definition of (UINT32) TPMA_OBJECT Bits
+
+Bit
+
+Name
+
+Definition
+
+0
+
+Reserved
+
+shall be zero
+
+1
+
+fixedTPM
+
+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.
+
+2
+
+stClear
+
+SET (1): Previously saved contexts of this object may not be loaded after
+Startup(CLEAR).
+CLEAR (0): Saved contexts of this object may be used after a
+Shutdown(STATE) and subsequent Startup().
+
+3
+
+Reserved
+
+shall be zero
+
+4
+
+fixedParent
+
+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.
+
+5
+
+sensitiveDataOrigin
+
+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.
+
+6
+
+userWithAuth
+
+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.
+
+7
+
+adminWithPolicy
+
+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.
+
+9:8
+
+Reserved
+
+shall be zero
+
+10
+
+noDA
+
+SET (1): The object is not subject to dictionary attack protections.
+CLEAR (0): The object is subject to dictionary attack protections.
+
+11
+
+encryptedDuplication
+
+SET (1): If the object is duplicated, then symmetricAlg shall not be
+TPM_ALG_NULL and newParentHandle shall not be TPM_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 TPM_RH_NULL.
+
+15:12 Reserved
+16
+
+restricted
+
+Page 56
+October 31, 2013
+
+shall be zero
+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.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Bit
+
+Name
+
+Definition
+
+17
+
+decrypt
+
+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.
+
+18
+
+sign
+
+SET (1): 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.
+
+31:19 Reserved
+
+8.3.3
+8.3.3.1
+
+shall be zero
+
+Attribute Descriptions
+Introduction
+
+The following remaining paragraphs in this clause describe the use and settings for each of the
+TPMA_OBJECT attributes. The description includes checks that are performed on the objectAttributes
+when an object is created, when it is loaded, and when it is imported. In these descriptions:
+Creation –
+
+indicates
+settings
+for
+TPM2_CreatePrimary()
+
+the
+
+template
+
+parameter
+
+in
+
+TPM2_Create()
+
+or
+
+Load
+
+–
+
+indicates settings for the inPublic parameter in TPM2_Load()
+
+Import
+
+–
+
+indicates settings for the objectPublic parameter in TPM2_Import()
+
+External
+
+–
+
+indicates settings that apply to the inPublic parameter in TPM2_LoadExternal() if both the
+public and sensitive portions of the object are loaded
+
+NOTE
+
+For TPM2_LoadExternal() when only the public portion of the object is loaded, the only attribute checks
+are the checks in the validation code following Table 30 and the reserved attributes check.
+
+For any consistency error of attributes in TPMA_OBJECT, the TPM shall return TPM_RC_ATTRIBUTES.
+8.3.3.2
+
+Bit[1] – fixedTPM
+
+When SET, the object cannot be duplicated for use on a different TPM, either directly or indirectly and the
+Qualified Name of the object cannot change. When CLEAR, the object’s Qualified Name may change if
+the object or an ancestor is duplicated.
+NOTE
+
+This attribute is the logical inverse of the migratable attribute in 1.2. That is, when this attribute is C LEAR,
+it is the equivalent to a 1.2 object with migratable SET.
+
+Creation –
+
+If fixedTPM is SET in the object's parent, then fixedTPM and fixedParent shall both be
+set to the same value in template. If fixedTPM is CLEAR in the parent, this attribute shall
+also be CLEAR in template.
+NOTE
+
+For a Primary Object, the parent is considered to have fixedTPM SET.
+
+Load
+
+–
+
+If fixedTPM is SET in the object's parent, then fixedTPM and fixedParent shall both be
+set to the same value. If fixedTPM is CLEAR in the parent, this attribute shall also be
+CLEAR.
+
+Import
+
+–
+
+shall be CLEAR
+
+External
+
+–
+
+shall be CLEAR if both the public and sensitive portions are loaded or if fixedParent is
+CLEAR, otherwise may be SET or CLEAR
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 57
+October 31, 2013
+
+ Part 2: Structures
+8.3.3.3
+
+Trusted Platform Module Library
+
+Bit[2] – stClear
+
+If this attribute is SET, then saved contexts of this object will be invalidated on
+TPM2_Startup(TPM_SU_CLEAR). If the attribute is CLEAR, then the TPM shall not invalidate the saved
+context if the TPM received TPM2_Shutdown(TPM_SU_STATE). If the saved state is valid when checked
+at the next TPM2_Startup(), then the TPM shall continue to be able to use the saved contexts.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.4
+
+Bit[4] – fixedParent
+
+If this attribute is SET, the object’s parent may not be changed. That is, this object may not be the object
+of a TPM2_Duplicate(). If this attribute is CLEAR, then this object may be the object of a
+TPM2_Duplicate().
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+shall be CLEAR
+
+External
+
+–
+
+shall be CLEAR if both the public and sensitive portions are loaded; otherwise it may be
+SET or CLEAR
+
+8.3.3.5
+
+Bit[5] – sensitiveDataOrigin
+
+This attribute is SET for any key that was generated by TPM in TPM2_Create() or
+TPM2_CreatePrimary(). If CLEAR, it indicates that the sensitive part of the object (other than the
+obfuscation value) was provided by the caller.
+NOTE 1
+
+If the fixedTPM attribute is SET, then this attribute is authoritative and accurately reflects the source of
+the sensitive area data. If the fixedTPM attribute is CLEAR, then validation of this attribute requires
+evaluation of the properties of the ancestor keys.
+
+Creation –
+
+If inSensitive.sensitive.data.size is zero, then this attribute shall be SET in the template;
+otherwise, it shall be CLEAR in the template.
+
+NOTE 2
+
+The inSensitive.sensitive.data.size parameter is required to be zero for an asymmetric key so
+sensitiveDataOrigin is required to be SET.
+
+NOTE 3
+
+The inSensitive.sensitive.data.size parameter may not be zero for a data object so sensitiveDataOrigin is
+required to be CLEAR. A data object has type = TPM_ALG_KEYEDHASH and its sign and decrypt
+attributes are CLEAR.
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+Page 58
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.3.3.6
+
+Part 2: Structures
+
+Bit[6] – userWithAuth
+
+If SET, authorization for operations that require USER role authorization may be given if the caller
+provides proof of knowledge of the authValue of the object with an HMAC authorization session or a
+password.
+If this attribute is CLEAR, then then HMAC or password authorizations may not be used for USER role
+authorizations.
+NOTE 1
+
+Regardless of the setting of this attribute, authorizations for operations th at require USER role
+authorizations may be provided with a policy session that satisfies the object's authPolicy.
+
+NOTE 2
+
+Regardless of the setting of this attribute, the authValue may be referenced in a policy session or used to
+provide the bind value in TPM2_StartAuthSession(). However, if userWithAuth is CLEAR, then the object
+may be used as the bind object in TPM2_StartAuthSession() but the session cannot be used to authorize
+actions on the object. If this were allowed, then the userWithAuth control could be circumvented simply by
+using the object as the bind object.
+
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.7
+
+Bit[7] – adminWithPolicy
+
+If CLEAR, authorization for operations that require ADMIN role may be given if the caller provides proof of
+knowledge of the authValue of the object with an HMAC authorization session or a password.
+If this attribute is SET, then then HMAC or password authorizations may not be used for ADMIN role
+authorizations.
+NOTE 1
+
+Regardless of the setting of this attribute, operations that require ADMIN role authorization may be
+provided by a policy session that satisfies the object's authPolicy.
+
+NOTE 2
+
+This attribute is similar to userWithAuth but the logic is a bit different. When userWithAuth is CLEAR, the
+authValue may not be used for USER mode authorizations. When adminWithPolicy is CLEAR, it means
+that the authValue may be used for ADMIN role. Policy may always be used regardless of t he setting of
+userWithAuth or adminWithPolicy.
+
+Actions that always require policy (TPM2_Duplicate()) are not affected by the setting of this attribute.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.8
+
+Bit[10] – noDA
+
+If SET, then authorization failures for the object do not affect the dictionary attack protection logic and
+authorization of the object is not blocked if the TPM is in lockout.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 59
+October 31, 2013
+
+ Part 2: Structures
+8.3.3.9
+
+Trusted Platform Module Library
+
+Bit[11] – encryptedDuplication
+
+If SET, then when the object is duplicated, the sensitive portion of the object is required to be encrypted
+with an inner wrapper and the new parent shall be an asymmetric key and not TPM_RH_NULL
+NOTE 1
+
+Enforcement of these requirements in TPM2_Duplicate() is by not allowing symmetricAlg to be
+TPM_ALG_NULL and newParentHandle may not be TPM_RH_NULL.
+
+This attribute shall not be SET in any object that has fixedTPM SET.
+NOTE 2
+
+This requirement means that encryptedDuplication may not be SET if the object cannot be directly or
+indirectly duplicated.
+
+If an object's parent has fixedTPM SET, and the object is duplicable (fixedParent == CLEAR), then
+encryptedDuplication may be SET or CLEAR in the object.
+NOTE 3
+
+This allows the object at the boundary between duplicable and non -duplicable objects to have either
+setting.
+
+If an object's parent has fixedTPM CLEAR, then the object is required to have the same setting of
+encryptedDuplication as its parent.
+NOTE 4
+
+This requirement forces all
+encryptedDuplication setting.
+
+duplicable
+
+objects
+
+in
+
+a
+
+duplication
+
+group
+
+to
+
+have
+
+the
+
+same
+
+Creation –
+
+shall be CLEAR if fixedTPM is SET. If fixedTPM is CLEAR, then this attribute shall have
+the same value as its parent unless fixedTPM is SET in the object's parent, in which
+case, it may be SET or CLEAR.
+
+Load
+
+–
+
+shall be CLEAR if fixedTPM is SET. If fixedTPM is CLEAR, then this attribute shall have
+the same value as its parent, unless fixedTPM is SET the parent, in which case, it may
+be SET or CLEAR.
+
+Import
+
+–
+
+if fixedTPM is SET in the object's new parent, then this attribute may be SET or CLEAR,
+otherwise, it shall have the same setting as the new parent.
+
+External
+
+–
+
+may be SET or CLEAR.
+
+8.3.3.10
+
+Bit[16] – restricted
+
+This this attribute modifies the decrypt and sign attributes of an object.
+NOTE
+
+A key with this object CLEAR may not be a parent for another object.
+
+Creation –
+
+shall be CLEAR in template if neither sign nor decrypt is SET in template.
+
+Load
+
+–
+
+shall be CLEAR if neither sign nor decrypt is SET in the object
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+shall be CLEAR
+
+Page 60
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.3.3.11
+
+Part 2: Structures
+
+Bit[17] – decrypt
+
+When SET, the private portion of this key can be used to decrypt an external blob. If restricted is SET,
+then the TPM will return an error if the external decrypted blob is not formatted as appropriate for the
+command.
+NOTE 1
+
+Since TPM-generated keys and sealed data will contain a hash and a structure tag, the TPM can ensure
+that it is not being used to improperly decrypt and return sensitive data that should not be returned. The
+only type of data that may be returned after decryption is a Sealed Data Object (a keyedHash object with
+decrypt and sign CLEAR).
+
+When restricted is CLEAR, there are no restrictions on the use of the private portion of the key for
+decryption and the key may be used to decrypt and return any structure encrypted by the public portion of
+the key.
+NOTE 2
+
+A key with this attribute SET may be a parent for another object if restricted is SET and sign is CLEAR.
+
+If decrypt is SET on an object with type set to TPM_ALG_KEYEDHASH, it indicates that the object is an
+XOR encryption key.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.12
+
+Bit[18] – sign
+
+When this attribute is SET, the private portion of this key may be used to sign a digest. If restricted is
+SET, then the key may only be used to sign a digest that was computed by the TPM. A restricted signing
+key may be used to sign a TPM-generated digest. If a structure is generated by the TPM, it will begin with
+TPM_GENERATED_VALUE and the TPM may sign the digest of that structure. If the data is externally
+supplied and has TPM_GENERATED_VALUE as its first octets, then the TPM will not sign a digest of
+that data with a restricted signing key.
+If restricted is CLEAR, then the key may be used to sign any digest, whether generated by the TPM or
+externally provided.
+NOTE 1
+
+Some asymmetric algorithms may not support both sign and decrypt being SET in the same key.
+
+If sign is SET on an object with type set to TPM_ALG_KEYEDHASH, it indicates that the object is an
+HMAC key.
+NOTE 2
+
+A key with this attribute SET may not be a parent for another object.
+
+Creation –
+
+shall not be SET if decrypt and restricted are both SET
+
+Load
+
+–
+
+shall not be SET if decrypt and restricted are both SET
+
+Import
+
+–
+
+shall not be SET if decrypt and restricted are both SET
+
+External
+
+–
+
+shall not be SET if decrypt and restricted are both SET
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 61
+October 31, 2013
+
+ Part 2: Structures
+8.4
+
+Trusted Platform Module Library
+
+TPMA_SESSION (Session Attributes)
+
+This octet in each session is used to identify the session type, indicate its relationship to any handles in
+the command, and indicate its use in parameter encryption.
+Table 31 — Definition of (UINT8) TPMA_SESSION Bits <IN/OUT>
+Bit
+
+Name
+
+Meaning
+
+0
+
+continueSession
+
+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.
+
+1
+
+auditExclusive
+
+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.
+CLEAR (0): If audit is CLEAR, then this field is reserved but the error is
+TPM_RC_ATTRIBUTES rather than TPM_RC_RESERVED_BITS.
+See "Exclusive Audit Session" clause in Part 1.
+
+2
+
+auditReset
+
+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.
+CLEAR (0): If audit is CLEAR, then this field is reserved but the error is
+TPM_RC_ATTRIBUTES rather than TPM_RC_RESERVED_BITS. This setting is
+always used for a response.
+
+4:3
+
+Reserved
+
+shall be CLEAR
+
+decrypt
+
+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 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.
+
+5
+
+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_).
+
+Page 62
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Bit
+
+Name
+
+Meaning
+
+6
+
+encrypt
+
+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
+Part 1 of this specification.
+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_).
+
+7
+
+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.
+
+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.
+
+8.5
+
+TPMA_LOCALITY (Locality Attribute)
+
+In a TPMS_CREATION_DATA structure, this structure is used to indicate the locality of the command that
+created the object. No more than one of the locality attributes shall be set in the creation data.
+When used in TPM2_PolicyLocality(), this structure indicates which localities are approved by the policy.
+When a policy is started, all localities are allowed. If TPM2_PolicyLocality() is executed, it indicates that
+the command may only be executed at specific localities. More than one locality may be selected.
+EXAMPLE 1
+
+TPM_LOC_TWO would indicate that only locality 2 is authorized.
+
+EXAMPLE 2
+
+TPM_LOC_ONE + TPM_LOC_TWO would indicate that locality 1 or 2 is authorized.
+
+EXAMPLE 3
+
+TPM_LOC_FOUR + TPM_LOC_THREE would indicate that localities 3 or 4 are authorized.
+
+EXAMPLE 4
+
+A value of 21 16 would represent a locality of 33.
+
+NOTE
+
+Locality values of 5 through 31 are not selectable.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 63
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+If Extended is non-zero, then an extended locality is indicated and the TPMA_LOCALITY contains an
+integer value.
+Table 32 — Definition of (UINT8) TPMA_LOCALITY Bits <IN/OUT>
+Bit
+
+Name
+
+Definition
+
+0
+
+TPM_LOC_ZERO
+
+1
+
+TPM_LOC_ONE
+
+2
+
+TPM_LOC_TWO
+
+3
+
+TPM_LOC_THREE
+
+4
+
+TPM_LOC_FOUR
+
+7:5
+
+8.6
+
+Extended
+
+If any of these bits is set, an extended locality is indicated
+
+TPMA_PERMANENT
+
+The attributes in this structure are persistent and are not changed as a result of _TPM_Init or any
+TPM2_Startup(). Some of the attributes in this structure may change as the result of specific Protected
+Capabilities.
+This
+structure
+may
+be
+read
+using
+TPM2_GetCapability(capability
+=
+TPM_CAP_TPM_PROPERTIES, property = TPM_PT_PERMANENT).
+Table 33 — Definition of (UINT32) TPMA_PERMANENT Bits <OUT>
+Bit
+
+Parameter
+
+Description
+
+0
+
+ownerAuthSet
+
+SET (1): TPM2_HierarchyChangeAuth() with ownerAuth has been executed since
+the last TPM2_Clear().
+CLEAR (0): ownerAuth has not been changed since TPM2_Clear().
+
+1
+
+endorsementAuthSet
+
+SET (1): TPM2_HierarchyChangeAuth() with endorsementAuth has been executed
+since the last TPM2_Clear().
+CLEAR (0): endorsementAuth has not been changed since TPM2_Clear().
+
+2
+
+lockoutAuthSet
+
+SET (1): TPM2_HierarchyChangeAuth() with lockoutAuth has been executed since
+the last TPM2_Clear().
+CLEAR (0): lockoutAuth has not been changed since TPM2_Clear().
+
+7:3
+8
+
+Reserved
+disableClear
+
+SET (1): TPM2_Clear() is disabled.
+CLEAR (0): TPM2_Clear() is enabled.
+NOTE
+
+See “TPM2_ClearControl” in Part 3 of this specification for details on changing
+this attribute.
+
+9
+
+inLockout
+
+SET (1): The TPM is in lockout and commands that require authorization with other
+than platformAuth will not succeed.
+
+10
+
+tpmGeneratedEPS
+
+SET (1): The EPS was created by the TPM.
+CLEAR (0): The EPS was created outside of the TPM using a manufacturerspecific process.
+
+31:11 Reserved
+
+Page 64
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.7
+
+Part 2: Structures
+
+TPMA_STARTUP_CLEAR
+
+These attributes are set to their default state on reset on each TPM Reset or TPM Restart. The attributes
+are preserved on TPM Resume.
+On each TPM2_Startup(TPM_SU_CLEAR), the TPM will set these attributes to their indicated defaults.
+This structure may be read using TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES,
+property = TPM_PT_STARTUP_CLEAR).
+Some of attributes may be changed as the result of specific Protected Capabilities.
+Table 34 — Definition of (UINT32) TPMA_STARTUP_CLEAR Bits <OUT>
+Bit
+0
+
+Parameter
+
+Description
+
+phEnable
+
+SET (1): (default) 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 NV Indexes and persistent objects,
+cannot be used.
+NOTE
+
+1
+
+shEnable
+
+SET (1): (default) The Storage hierarchy is enabled and ownerAuth or ownerPolicy
+may be used for authorization.
+CLEAR (0): ownerAuth and ownerPolicy may not be used for authorizations, and
+objects in the Storage hierarchy, including NV Indexes and persistent objects,
+cannot be used.
+NOTE
+
+2
+
+ehEnable
+
+phEnableNV
+
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on
+changing this attribute.
+
+SET (1): (default) The EPS hierarchy is enabled and endorsementAuth may be
+used to authorize commands.
+CLEAR (0): endorsementAuth and endorsementPolicy may not be used for
+authorizations, and objects in the endorsement hierarchy, including persistent
+objects, cannot be used.
+NOTE
+
+3
+
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on
+changing this attribute.
+
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on
+changing this attribute.
+
+SET (1): (default) 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 (TPM_RC_HANDLE). The platform cannot
+define
+(TPM_RC_HIERARCHY) or undefined (TPM_RC_HANDLE) indices.
+NOTE
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on changing
+this attribute.
+NOTE
+read refers to these commands: TPM2_NV_Read, TPM2_NV_ReadPublic, TPM_NV_Certify,
+TPM2_PolicyNV
+write refers to thse commands: TPM2_NV_Write, TPM2_NV_Increment, TPM2_NV_Extend,
+TPM2_NV_SetBits
+NOTE The TPM must query the index TPMA_PLATFORM_CREATE attribute to determine
+whether phEnableNV is applicable. Since the TPM will return TPM_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.
+
+30:4 Reserved
+
+Family “2.0”
+Level 00 Revision 00.99
+
+shall be zero
+
+Published
+Copyright © TCG 2006-2013
+
+Page 65
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Bit
+
+Parameter
+
+Description
+
+31
+
+orderly
+
+SET (1): The TPM received a TPM2_Shutdown() and a matching TPM2_Startup().
+CLEAR (0): TPM2_Startup(TPM_SU_CLEAR) was not preceded by a
+TPM2_Shutdown() of any type.
+NOTE
+
+8.8
+
+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_Startup(TPM_SU_STATE)
+was
+not
+preceded
+by
+TPM2_State_Save(TPM_SU_STATE).
+
+TPMA_MEMORY
+
+This structure of this attribute is used to report the memory management method used by the TPM for
+transient
+objects
+and
+authorization
+sessions.
+This
+structure
+may be
+read
+using
+TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES, property = TPM_PT_MEMORY).
+If the RAM memory is shared, then context save of a session may make it possible to load an additional
+transient object.
+Table 35 — Definition of (UINT32) TPMA_MEMORY Bits <Out>
+Bit
+
+Name
+
+Definition
+
+0
+
+sharedRAM
+
+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
+
+1
+
+sharedNV
+
+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
+
+2
+
+objectCopiedToRam
+
+SET (1): indicates that the TPM copies persistent objects to a transient-object
+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 transient-object slots when
+persistent objects are referenced
+
+31:3
+
+Reserved
+
+shall be zero
+
+Page 66
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.9
+
+Part 2: Structures
+
+TPMA_CC (Command Code Attributes)
+
+8.9.1
+
+Introduction
+
+This structure defines the attributes of a command from a context management perspective. The fields of
+the structure indicate to the TPM Resource Manager (TRM) the number of resources required by a
+command and how the command affects the TPM’s resources.
+This structure is only used in a list returned by the TPM in response to TPM2_GetCapability(capability =
+TPM_CAP_COMMANDS).
+For a command to the TPM, only the commandIndex field and V attribute are allowed to be non-zero.
+8.9.2
+
+Structure Definition
+Table 36 — Definition of (TPM_CC) TPMA_CC Bits <OUT>
+
+Bit
+15:0
+
+Name
+
+Definition
+
+commandIndex
+
+indicates the command being selected
+
+21:16 Reserved
+
+shall be zero
+
+22
+
+nv
+
+SET (1): indicates that the command may write to NV
+CLEAR (0): indicates that the command does not write to NV
+
+23
+
+extensive
+
+SET (1): This command could flush any number of loaded contexts.
+CLEAR (0): no additional changes other than indicated by the flushed attribute
+
+24
+
+flushed
+
+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.
+
+27:25 cHandles
+
+indicates the number of the handles in the handle area for this command
+
+28
+
+rHandle
+
+SET (1): indicates the presence of the handle area in the input
+
+29
+
+V
+
+SET (1): indicates that the command is vendor-specific
+CLEAR (0): indicates that the command is defined in a version of this
+specification
+
+31:30 Res
+
+8.9.3
+8.9.3.1
+
+allocated for software; shall be zero
+
+Field Descriptions
+Bits[15:0] – commandIndex
+
+This is the command index of the command in the set of commands. The two sets are defined by the V
+attribute. If V is zero, then the commandIndex shall be in the set of commands defined in a version of this
+specification. If V is one, then the meaning of commandIndex is as determined by the TPM vendor.
+8.9.3.2
+
+Bit[22] – nv
+
+If this attribute is SET, then the TPM may perform an NV write as part of the command actions. This write
+is independent of any write that may occur as a result of dictionary attack protection. If this attribute is
+CLEAR, then the TPM shall not perform an NV write as part of the command actions.
+8.9.3.3
+
+Bit[23] – extensive
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 67
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+If this attribute is SET, then the TPM may flush many transient objects as a side effect of this command.
+In Part 3, a command that has this attribute is indicated by using a “{E}” decoration in the “Description”
+column of the commandCode parameter.
+EXAMPLE
+
+See “TPM2_Clear” in Part 3.
+
+NOTE
+
+The “{E}” decoration may be combined with other decorations such as “{NV}” in which case the decoration
+would be “{NV E}.”
+
+8.9.3.4
+
+Bit[24] – flushed
+
+If this attribute is SET, then the TPM will flush transient objects as a side effect of this command. Any
+transient objects listed in the handle area of the command will be flushed from TPM memory. Handles
+associated with persistent objects, sessions, PCR, or other fixed TPM resources are not flushed.
+NOTE
+
+The TRM is expected to use this value to determine how many objects are loaded into transient TPM
+memory.
+
+NOTE
+
+The “{F}” decoration may be combined with other decorations such as “{NV}” in which case the decoration
+would be “{NV F}.”
+
+If this attribute is SET for a command, and the handle of the command is associated with a hierarchy
+(TPM_RH_PLATFORM, TPM_RH_OWNER, or TPM_RH_ENDORSEMENT), all loaded objects in the
+indicated hierarchy are flushed.
+The TRM is expected to know the behaviour of TPM2_ContextSave(), and sessions are flushed when
+context saved, but objects are not. The flushed attribute for that command shall be CLEAR.
+In Part 3, a command that has this attribute is indicated by using a “{F}” decoration in the “Description”
+column of the commandCode parameter.
+EXAMPLE
+
+8.9.3.5
+
+See “TPM2_SequenceComplete” in Part 3.”
+
+Bits[27:25] – cHandles
+
+This field indicates the number of handles in the handle area of the command. This number allows the
+TRM to enumerate the handles in the handle area and find the position of the authorizations (if any).
+8.9.3.6
+
+Bit[28] – rHandle
+
+If this attribute is SET, then the response to this command has a handle area. This area will contain no
+more than one handle. This field is necessary to allow the TRM to locate the parameterSize field in the
+response, which is then used to locate the authorizations.
+NOTE
+
+The TRM is expected to “virtualize” the handle value for any returned handle.
+
+Page 68
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+A TPM command is only allowed to have one handle in the session area.
+8.9.3.7
+
+Bit[29] – V
+
+When this attribute is SET, it indicates that the command operation is defined by the TPM vendor. When
+CLEAR, it indicates that the command is defined by a version of this specification.
+8.9.3.8
+
+Bits[31:30] – Res
+
+This field is reserved for system software. This field is required to be zero for a command to the TPM.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 69
+October 31, 2013
+
+ Part 2: Structures
+
+9
+
+Trusted Platform Module Library
+
+Interface Types
+
+9.1
+
+Introduction
+
+This clause contains definitions for interface types. An interface type is type checked when it is
+unmarshaled. These types are based on an underlying type that is indicated in the table title by the value
+in parentheses. When an interface type is used, the base type is unmarshaled and then checked to see if
+it has one of the allowed values.
+9.2
+
+TPMI_YES_NO
+
+This interface type is used in place of a Boolean type in order to eliminate ambiguity in the handling of a
+octet that conveys a single bit of information. This type only has two allowed values, YES (1) and NO (0).
+NOTE
+
+This list is not used as input to the TPM.
+
+Table 37 — Definition of (BYTE) TPMI_YES_NO Type
+Value
+
+Description
+
+NO
+
+a value of 0
+
+YES
+
+a value of 1
+
+#TPM_RC_VALUE
+
+9.3
+
+TPMI_DH_OBJECT
+
+The TPMI_DH_OBJECT interface type is a handle that references a loaded object. The handles in this
+set are used to refer to either transient or persistent object. The range of these values would change
+according to the TPM implementation.
+NOTE
+
+These interface types should not be used by system software to qualify the keys produced by the TPM.
+The value returned by the TPM shall be used to reference the object.
+
+Table 38 — Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type
+Values
+
+Comments
+
+{TRANSIENT_FIRST:TRANSIENT_LAST}
+
+allowed range for transient objects
+
+{PERSISTENT_FIRST:PERSISTENT_LAST}
+
+allowed range for persistent objects
+
++TPM_RH_NULL
+
+the conditional value
+
+#TPM_RC_VALUE
+
+Page 70
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+9.4
+
+Part 2: Structures
+
+TPMI_DH_PERSISTENT
+
+The TPMI_DH_PERSISTENT interface type is a handle that references a location for a transient object.
+This type is used in TPM2_EvictControl() to indicate the handle to be assigned to the persistent object.
+Table 39 — Definition of (TPM_HANDLE) TPMI_DH_PERSISTENT Type
+Values
+
+Comments
+
+{PERSISTENT_FIRST:PERSISTENT_LAST}
+
+allowed range for persistent objects
+
+#TPM_RC_VALUE
+
+9.5
+
+TPMI_DH_ENTITY
+
+The TPMI_DH_ENTITY interface type is TPM-defined values that are used to indicate that the handle
+refers to an authValue. The range of these values would change according to the TPM implementation.
+Table 40 — Definition of (TPM_HANDLE) TPMI_DH_ENTITY Type <IN>
+Values
+
+Comments
+
+TPM_RH_OWNER
+TPM_RH_ENDORSEMENT
+TPM_RH_PLATFORM
+TPM_RH_LOCKOUT
+{TRANSIENT_FIRST : TRANSIENT_LAST}
+
+range of object handles
+
+{PERSISTENT_FIRST : PERSISTENT_LAST}
+{NV_INDEX_FIRST : NV_INDEX_LAST}
+{PCR_FIRST : PCR_LAST}
++TPM_RH_NULL
+
+conditional value
+
+#TPM_RC_VALUE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 71
+October 31, 2013
+
+ Part 2: Structures
+9.6
+
+Trusted Platform Module Library
+
+TPMI_DH_PCR
+
+This interface type consists of the handles that may be used as PCR references. The upper end of this
+range of values would change according to the TPM implementation.
+NOTE 1
+
+Typically, the 0 th PCR will have a handle value of zero.
+
+NOTE 2
+
+The handle range for PCR is defined to be the same as the handle range for PCR in previous versions of
+TPM specifications.
+
+Table 41 — Definition of (TPM_HANDLE) TPMI_DH_PCR Type <IN>
+Values
+
+Comments
+
+{PCR_FIRST:PCR_LAST}
++TPM_RH_NULL
+
+conditional value
+
+#TPM_RC_VALUE
+
+9.7
+
+TPMI_SH_AUTH_SESSION
+
+The TPMI_SH_AUTH_SESSION interface type is TPM-defined values that are used to indicate that the
+handle refers to an authorization session.
+Table 42 — Definition of (TPM_HANDLE) TPMI_SH_AUTH_SESSION Type <IN/OUT>
+Values
+
+Comments
+
+{HMAC_SESSION_FIRST : HMAC_SESSION_LAST}
+
+range of HMAC authorization session handles
+
+{POLICY_SESSION_FIRST: POLICY_SESSION_LAST}
+
+range of policy authorization session handles
+
++TPM_RS_PW
+
+a password authorization
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+9.8
+
+TPMI_SH_HMAC
+
+This interface type is used for an authorization handle when the authorization session uses an HMAC.
+Table 43 — Definition of (TPM_HANDLE) TPMI_SH_HMAC Type <IN/OUT>
+Values
+
+Comments
+
+{HMAC_SESSION_FIRST: HMAC_SESSION_LAST}
+
+range of HMAC authorization session handles
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+9.9
+
+TPMI_SH_POLICY
+
+This interface type is used for a policy handle when it appears in a policy command.
+Table 44 — Definition of (TPM_HANDLE) TPMI_SH_POLICY Type <IN/OUT>
+Values
+
+Comments
+
+{POLICY_SESSION_FIRST: POLICY_SESSION_LAST}
+
+range of policy authorization session handles
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+Page 72
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.10 TPMI_DH_CONTEXT
+This type defines the handle values that may be used in TPM2_ContextSave() or TPM2_Flush().
+Table 45 — Definition of (TPM_HANDLE) TPMI_DH_CONTEXT Type
+Values
+
+Comments
+
+{HMAC_SESSION_FIRST : HMAC_SESSION_LAST}
+{POLICY_SESSION_FIRST:POLICY_SESSION_LAST}
+{TRANSIENT_FIRST:TRANSIENT_LAST}
+#TPM_RC_VALUE
+
+9.11 TPMI_RH_HIERARCHY
+The TPMI_RH_HIERARCHY interface type is used as the type of a handle in a command when the
+handle is required to be one of the hierarchy selectors.
+Table 46 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY Type
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Storage hierarchy
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
++TPM_RH_NULL
+
+no hierarchy
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.12 TPMI_RH_ENABLES
+The TPMI_RH_ENABLES interface type is used as the type of a handle in a command when the handle
+is required to be one of the hierarchy or NV enables.
+Table 47 — Definition of (TPM_HANDLE) TPMI_RH_ENABLES Type
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Storage hierarchy
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
+TPM_RH_PLATFORM_NV
+
+Platform NV
+
++TPM_RH_NULL
+
+no hierarchy
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 73
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.13 TPMI_RH_HIERARCHY_AUTH
+This interface type is used as the type of a handle in a command when the handle is required to be one of
+the hierarchy selectors or the Lockout Authorization.
+Table 48 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_AUTH Type <IN>
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Storage hierarchy
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
+TPM_RH_LOCKOUT
+
+Lockout Authorization
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.14 TPMI_RH_PLATFORM
+The TPMI_RH_PLATFORM interface type is used as the type of a handle in a command when the only
+allowed handle is TPM_RH_PLATFORM indicating that platformAuth is required.
+Table 49 — Definition of (TPM_HANDLE) TPMI_RH_PLATFORM Type <IN>
+Values
+
+Comments
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.15 TPMI_RH_OWNER
+This interface type is used as the type of a handle in a command when the only allowed handle is
+TPM_RH_OWNER indicating that ownerAuth is required.
+Table 50 — Definition of (TPM_HANDLE) TPMI_RH_OWNER Type <IN>
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Owner hierarchy
+
++TPM_RH_NULL
+
+may allow the null handle
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+Page 74
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.16 TPMI_RH_ENDORSEMENT
+This interface type is used as the type of a handle in a command when the only allowed handle is
+TPM_RH_ENDORSEMENT indicating that endorsementAuth is required.
+Table 51 — Definition of (TPM_HANDLE) TPMI_RH_ENDORSEMENT Type <IN>
+Values
+
+Comments
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
++TPM_RH_NULL
+
+may allow the null handle
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.17 TPMI_RH_PROVISION
+The TPMI_RH_PROVISION interface type is used as the type of the handle in a command when the only
+allowed handles are either TPM_RH_OWNER or TPM_RH_PLATFORM indicating that either
+platformAuth or ownerAuth are allowed.
+In most cases, either platformAuth or ownerAuth may be used to authorize the commands used for
+management of the resources of the TPM and this interface type will be used.
+Table 52 — Definition of (TPM_HANDLE) TPMI_RH_PROVISION Type <IN>
+Value
+
+Comments
+
+TPM_RH_OWNER
+
+handle for ownerAuth
+
+TPM_RH_PLATFORM
+
+handle for platformAuth
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.18 TPMI_RH_CLEAR
+The TPMI_RH_CLEAR interface type is used as the type of the handle in a command when the only
+allowed handles are either TPM_RH_LOCKOUT or TPM_RH_PLATFORM indicating that either
+platformAuth or lockoutAuth are allowed.
+This interface type is normally used for performing or controlling TPM2_Clear().
+Table 53 — Definition of (TPM_HANDLE) TPMI_RH_CLEAR Type <IN>
+Value
+
+Comments
+
+TPM_RH_LOCKOUT
+
+handle for lockoutAuth
+
+TPM_RH_PLATFORM
+
+handle for platformAuth
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 75
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.19 TPMI_RH_NV_AUTH
+This interface type is used to identify the source of the authorization for access to an NV location. The
+handle value of a TPMI_RH_NV_AUTH shall indicate that the authorization value is either platformAuth,
+ownerAuth, or the authValue. This type is used in the commands that access an NV Index (commands of
+the form TPM2_NV_xxx) other than TPM2_NV_DefineSpace() and TPM2_NV_UndefineSpace().
+Table 54 — Definition of (TPM_HANDLE) TPMI_RH_NV_AUTH Type <IN>
+Value
+
+Comments
+
+TPM_RH_PLATFORM
+
+platformAuth is allowed
+
+TPM_RH_OWNER
+
+ownerAuth is allowed
+
+{NV_INDEX_FIRST:NV_INDEX_LAST}
+
+range for NV locations
+
+#TPM_RC_VALUE
+
+response code returned when unmarshaling of this type fails
+
+9.20 TPMI_RH_LOCKOUT
+The TPMI_RH_LOCKOUT interface type is used as the type of a handle in a command when the only
+allowed handle is TPM_RH_LOCKOUT indicating that lockoutAuth is required.
+Table 55 — Definition of (TPM_HANDLE) TPMI_RH_LOCKOUT Type <IN>
+Value
+
+Comments
+
+TPM_RH_LOCKOUT
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.21 TPMI_RH_NV_INDEX
+This interface type is used to identify an NV location. This type is used in the NV commands.
+Table 56 — Definition of (TPM_HANDLE) TPMI_RH_NV_INDEX Type <IN/OUT>
+Value
+
+Comments
+
+{NV_INDEX_FIRST:NV_INDEX_LAST}
+
+Range of NV Indexes
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+Page 76
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.22 TPMI_ALG_HASH
+A TPMI_ALG_HASH is an interface type of all the hash algorithms implemented on a specific TPM. Table
+57 is a list of the hash algorithms that have an algorithm ID assigned by the TCG and does not indicate
+the algorithms that will be accepted by a TPM.
+NOTE
+
+An implementation would modify this table according to the implemented algorithms, changing the values
+that are accepted as hash algorithms.
+
+Table 57 — Definition of (TPM_ALG_ID) TPMI_ALG_HASH Type
+Values
+
+Comments
+
+TPM_ALG_SHA1
+
+example
+
+TPM_ALG_SHA256
+
+example
+
+TPM_ALG_SM3_256
+
+example
+
+TPM_ALG_SHA384
+
+example
+
+TPM_ALG_SHA512
+
+example
+
++TPM_ALG_NULL
+#TPM_RC_HASH
+
+9.23 TPMI_ALG_ASYM (Asymmetric Algorithms)
+A TPMI_ALG_ASYM is an interface type of all the asymmetric algorithms implemented on a specific TPM.
+Table 58 lists each of the asymmetric algorithms that have an algorithm ID assigned by the TCG.
+Table 58 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM Type
+Values
+
+Comments
+
+TPM_ALG_RSA
+TPM_ALG_ECC
++TPM_ALG_NULL
+#TPM_RC_ASYMMETRIC
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 77
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.24 TPMI_ALG_SYM (Symmetric Algorithms)
+A TPMI_ALG_SYM is an interface type of all the symmetric algorithms that have an algorithm ID assigned
+by the TCG and are implemented on the TPM.
+The list in the table below is illustrative and will change according to the implementation. The validation
+code will only accept the subset of algorithms implemented on a TPM.
+NOTE
+
+The validation code produced by an example script will produce a CASE statement with a case for each of
+the values in the “Values” column. The case for a value is delimited by a #ifdef/#endif pair so that if the
+algorithm is not implemented on the TPM, then the case for the algorithm is not generated, and use of the
+algorithm will cause a TPM error (TPM_RC_SYMMETRIC).
+
+Table 59 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM Type
+Values
+
+Comments
+
+TPM_ALG_AES
+
+example
+
+TPM_ALG_SM4
+
+example
+
+TPM_ALG_XOR
+
+example
+
++TPM_ALG_NULL
+
+required to be present in all versions of this table
+
+#TPM_RC_SYMMETRIC
+
+9.25 TPMI_ALG_SYM_OBJECT
+A TPMI_ALG_SYM_OBJECT is an interface type of all the TCG-defined symmetric algorithms that may
+be used as companion symmetric encryption algorithm for an asymmetric object. All algorithms in this list
+shall be block ciphers usable in Cipher Feedback (CFB).
+Table 60 is illustrative. It would be modified to indicate the algorithms of the TPM.
+NOTE
+
+TPM_ALG_XOR is not allowed in this list.
+
+Table 60 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_OBJECT Type
+Values
+
+Comments
+
+TPM_ALG_AES
+
+example
+
+TPM_ALG_SM4
+
+example
+
++TPM_ALG_NULL
+
+required to be present in all versions of this table
+
+#TPM_RC_SYMMETRIC
+
+Page 78
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.26 TPMI_ALG_SYM_MODE
+A TPMI_ALG_SYM_MODE is an interface type of all the TCG-defined block-cipher modes of operation.
+This version of the table is not expected to be the table checked by the validation code. Rather, the table
+would be replaced by one containing the algorithms implemented on the TPM and that the values in that
+table would be checked by the input validation code.
+Table 61 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_MODE Type
+Values
+
+Comments
+
+TPM_ALG_CTR
+
+IV will be determined by use.
+If the outside provides the nonce and initial counter, then the caller can
+know what IV to provide for chaining.
+
+TPM_ALG_OFB
+
+XOR last cipher text block with last plaintext to create IV for next block
+
+TPM_ALG_CBC
+
+IV will be determined by use.
+indefinite chaining using previous output block as IV for next block
+
+TPM_ALG_CFB
+
+shall be implemented in all TPM compliant with this specification
+IV will be determined by use.
+indefinite chaining using previous cipher text as IV
+
+TPM_ALG_ECB
+
+no IV or chaining value required
+
++TPM_ALG_NULL
+#TPM_RC_MODE
+
+9.27 TPMI_ALG_KDF (Key and Mask Generation Functions)
+A TPMI_ALG_KDF is an interface type of all the key derivation functions implemented on a specific TPM.
+Table 62 is exemplary and would change based on the algorithms implemented in a TPM.
+Table 62 — Definition of (TPM_ALG_ID) TPMI_ALG_KDF Type
+Values
+
+Comments
+
+TPM_ALG_MGF1
+TPM_ALG_KDF1_SP800_108
+TPM_ALG_KDF1_SP800_56a
+TPM_ALG_KDF2
++TPM_ALG_NULL
+#TPM_RC_KDF
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 79
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.28 TPMI_ALG_SIG_SCHEME
+This is the definition of the interface type for a signature scheme. This table would change according to
+the algorithms implemented on the TPM.
+Table 63 — Definition of (TPM_ALG_ID) TPMI_ALG_SIG_SCHEME Type
+Values
+
+Comments
+
+TPM_ALG_RSASSA
+
+requires that RSA be implemented
+
+TPM_ALG_RSAPSS
+
+requires that RSA be implemented
+
+TPM_ALG_ECDSA
+
+requires that ECC be implemented
+
+TPM_ALG_ECDAA
+
+requires that ECC and ECDAA be implemented
+
+TPM_ALG_ECSCHNORR
+TPM_ALG_SM2
+
+requires that ECC be implemented
+
+TPM_ALG_HMAC
+
+present on all TPM
+
++TPM_ALG_NULL
+#TPM_RC_SCHEME
+
+response code when a signature scheme is not correct
+
+9.29 TPMI_ECC_KEY_EXCHANGE
+This is the definition of the interface type for an ECC key exchange scheme. This table would change
+according to the algorithms implemented on the TPM.
+Table 64 — Definition of (TPM_ALG_ID) TPMI_ECC_KEY_EXCHANGE Type
+Values
+
+Comments
+
+TPM_ALG_ECDH
+
+used for single and two phase key exchange
+
+TPM_ALG_ECMQV
+TPM_ALG_SM2
+
+requires that ECC be implemented
+
++TPM_ALG_NULL
+#TPM_RC_SCHEME
+
+response code when a key exchange scheme is not correct
+
+9.30 TPMI_ST_COMMAND_TAG
+This interface type is used for the command tags.
+The response code for a bad command tag has the same value as the TPM 1.2 response code
+(TPM_BAD_TAG). This value is used in case the software is not compatible with this specification and an
+unexpected response code might have unexpected side effects.
+Table 65 — Definition of (TPM_ST) TPMI_ST_COMMAND_TAG Type
+Values
+
+Comments
+
+TPM_ST_NO_SESSIONS
+TPM_ST_SESSIONS
+#TPM_RC_BAD_TAG
+
+Page 80
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10 Structure Definitions
+10.1 TPMS_ALGORITHM_DESCRIPTION
+This structure is a return value for a TPM2_GetCapability() that reads the installed algorithms.
+Table 66 — Definition of TPMS_ALGORITHM_DESCRIPTION Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+alg
+
+TPM_ALG_ID
+
+an algorithm
+
+attributes
+
+TPMA_ALGORITHM
+
+the attributes of the algorithm
+
+10.2 Hash/Digest Structures
+10.2.1 TPMU_HA (Hash)
+A TPMU_HA is a union of all the hash algorithms implemented on a TPM. Table 67 is exemplary and
+would change based on the algorithms implemented in a TPM.
+NOTE
+
+If processed by an automated tool, each entry of the table should be qualified (with #ifdef/#endif) so that if
+the hash algorithm is not implemented on the TPM, the parameter associated with that hash is not
+present. This will keep the union from being larger than the largest digest of a hash implemented on that
+TPM.
+
+Table 67 — Definition of TPMU_HA Union <IN/OUT, S>
+Parameter
+
+Type
+
+Selector
+
+sha1 [SHA1_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA1
+
+sha256 [SHA256_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA256
+
+sm3_256 [SM3_256_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SM3_256
+
+sha384 [SHA384_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA384
+
+sha512 [SHA512_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA512
+
+null
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Description
+
+TPM_ALG_NULL
+
+Published
+Copyright © TCG 2006-2013
+
+Page 81
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.2.2 TPMT_HA
+Table 68 shows the basic hash-agile structure used in this specification. To handle hash agility, this
+structure uses the hashAlg parameter to indicate the algorithm used to compute the digest and, by
+implication, the size of the digest.
+When transmitted, only the number of octets indicated by hashAlg is sent.
+NOTE
+
+In the exemplary code, when a TPMT_HA is allocated, the digest field is large enough to support the
+largest hash algorithm in the TPMU_HA union.
+
+Table 68 — Definition of TPMT_HA Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+selector of the hash contained in the digest that implies the
+size of the digest
+NOTE
+
+[hashAlg] digest
+
+TPMU_HA
+
+The leading “+” on the type indicates that this structure
+should pass an indication to the unmarshaling function for
+TPMI_ALG_HASH so that TPM_ALG_NULL will be
+allowed if a use of a TPMT_HA allows TPM_ALG_NULL.
+
+the digest data
+
+10.3 Sized Buffers
+10.3.1 Introduction
+The “TPM2B_” prefix is used for a structure that has a size field followed by a data buffer with the
+indicated number of octets. The size field is 16 bits.
+When the type of the second parameter in a TPM2B_ structure is BYTE, the TPM shall unmarshal the
+indicated number of octets, which may be zero.
+When the type of the second parameter in the TPM2B_ structure is not BYTE, the value of the size field
+shall either be zero indicating that no structure is to be unmarshaled; or it shall be identical to the number
+of octets unmarshaled for the second parameter.
+NOTE 1
+
+If the TPM2B_ defines a structure and not an array of octets, then the structure is self-describing and the
+TPM will be able to determine how many octets are in the structure when it is unmarshaled. If that number
+of octets is not equal to the size parameter, then it is an error.
+
+NOTE 2
+
+The reason that a structure may be put into a TPM2B_ is that the parts of the structure may be handled
+as separate opaque blocks by the application/system software. Rather than require that all of the
+structures in a command or response be marshaled or unmarshaled sequentially, the size field allows the
+structure to be manipulated as an opaque block. Placing a structure in a TPM2B_ also makes it possible
+to use parameter encryption on the structure.
+
+If a TPM2B_ is encrypted, the TPM will encrypt/decrypt the data field of the TPM2B_ but not the size
+parameter. The TPM will encrypt/decrypt the number of octets indicated by the size field.
+NOTE 3
+
+In the reference implementation, a TPM2B type is defined that is a 16-bit size field followed by a single
+byte of data. The TPM2B_ is then defined as a union that contains a TPM2B (union member ‘b’) and the
+structure in the definition table (union member ‘t’). This union is used for internally generated structures
+so that there is a way to define a structure of the correct size (forced by the ‘t’ member) while giving a way
+to pass the structure generically as a ‘b’. Most function calls use the 't' member so that the compiler will
+generate a warning if there is a type error (a TPM2B_ of the wrong type). Having the type checked helps
+avoid many issues with buffer overflow caused by a too small buffer being passed to a function.
+
+Page 82
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.3.2 TPM2B_DIGEST
+This structure is used for a sized buffer that cannot be larger than the largest digest produced by any
+hash algorithm implemented on the TPM.
+As with all sized buffers, the size is checked to see if it is within the prescribed range. If not, the response
+code is TPM_RC_SIZE.
+NOTE
+
+For any structure, like the one below, that contains an implied size check, it is implied that TPM_RC_SIZE
+is a possible response code and the response code will not be listed in the table.
+
+Table 69 — Definition of TPM2B_DIGEST Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size in octets of the buffer field; may be 0
+
+buffer[size]{:sizeof(TPMU_HA)}
+
+BYTE
+
+the buffer area that can be no larger than a digest
+
+10.3.3 TPM2B_DATA
+This structure is used for a data buffer that is required to be no larger than the size of the Name of an
+object. This size limit includes the algorithm ID of the hash and the hash data.
+Table 70 — Definition of TPM2B_DATA Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size in octets of the buffer field; may be 0
+
+buffer[size]{:sizeof(TPMT_HA)}
+
+BYTE
+
+the buffer area that contains the algorithm ID and the
+digest
+
+10.3.4 TPM2B_NONCE
+Table 71 — Definition of Types for TPM2B_NONCE
+Type
+
+Name
+
+Description
+
+TPM2B_DIGEST
+
+TPM2B_NONCE
+
+size limited to the same as the digest structure
+
+10.3.5 TPM2B_AUTH
+This structure is used for an authorization value and limits an authValue to being no larger than the
+largest digest produced by a TPM. In order to ensure consistency within an object, the authValue may be
+no larger than the size of the digest produced by the object’s nameAlg. This ensures that any TPM that
+can load the object will be able to handle the authValue of the object.
+Table 72 — Definition of Types for TPM2B_AUTH
+Type
+
+Name
+
+Description
+
+TPM2B_DIGEST
+
+TPM2B_AUTH
+
+size limited to the same as the digest structure
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 83
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.3.6 TPM2B_OPERAND
+This type is a sized buffer that can hold an operand for a comparison with an NV Index location. The
+maximum size of the operand is implementation dependent but a TPM is required to support an operand
+size that is at least as big as the digest produced by any of the hash algorithms implemented on the TPM.
+Table 73 — Definition of Types for TPM2B_OPERAND
+Type
+
+Name
+
+Description
+
+TPM2B_DIGEST
+
+TPM2B_OPERAND
+
+size limited to the same as the digest structure
+
+10.3.7 TPM2B_EVENT
+This type is a sized buffer that can hold event data.
+Table 74 — Definition of TPM2B_EVENT Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the operand buffer
+
+buffer [size] {:1024}
+
+BYTE
+
+the operand
+
+10.3.8 TPM2B_MAX_BUFFER
+This type is a sized buffer that can hold a maximally sized buffer for commands that use a large data
+buffer
+such
+as
+TPM2_PCR_Event(),
+TPM2_Hash(),
+TPM2_SequenceUpdate(),
+or
+TPM2_FieldUpgradeData().
+NOTE
+
+The above list is not comprehensive and other commands may use this buffer type.
+
+Table 75 — Definition of TPM2B_MAX_BUFFER Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the buffer
+
+buffer [size] {:MAX_DIGEST_BUFFER}
+
+BYTE
+
+the operand
+NOTE
+MAX_DIGEST_BUFFER
+is
+TPMdependent but is required to be at least 1,024.
+
+10.3.9 TPM2B_MAX_NV_BUFFER
+This type is a sized buffer that can hold a maximally sized buffer for NV data commands such as
+TPM2_NV_Read(), TPM2_NV_Write(), and TPM2_NV_Certify().
+Table 76 — Definition of TPM2B_MAX_NV_BUFFER Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the buffer
+
+buffer [size] {:MAX_NV_BUFFER_SIZE}
+
+BYTE
+
+the operand
+NOTE
+MAX_NV_BUFFER_SIZE
+dependent
+
+Page 84
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+is
+
+TPM-
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.3.10 TPM2B_TIMEOUT
+This TPM-dependent structure is used to provide the timeout value for an authorization.
+Table 77 — Definition of TPM2B_TIMEOUT Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the timeout value
+This value is fixed for a TPM implementation.
+
+buffer [size] {:sizeof(UINT64)}
+
+BYTE
+
+the timeout value
+
+10.3.11 TPM2B_IV
+This structure is used for passing an initial value for a symmetric block cipher to or from the TPM. The
+size is set to be the largest block size of any implemented symmetric cipher implemented on the TPM.
+Table 78 — Definition of TPM2B_IV Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the timeout value
+This value is fixed for a TPM implementation.
+
+buffer [size] {:MAX_SYM_BLOCK_SIZE}
+
+BYTE
+
+the timeout value
+
+10.4 Names
+10.4.1 Introduction
+The Name of an entity is used in place of the handle in authorization computations. The substitution
+occurs in cpHash and policyHash computations.
+For an entity that is defined by a public area (objects and NV Indexes), the Name is the hash of the public
+structure that defines the entity. The hash is done using the nameAlg of the entity.
+NOTE
+
+For an object, a TPMT_PUBLIC defines the entity. For an NV Index, a TPMS_NV_PUBLIC defines the
+entity.
+
+For entities not defined by a public area, the Name is the handle that is used to refer to the entity.
+10.4.2 TPMU_NAME
+Table 79 — Definition of TPMU_NAME Union <>
+Parameter
+
+Type
+
+digest
+
+TPMT_HA
+
+when the Name is a digest
+
+handle
+
+TPM_HANDLE
+
+when the Name is a handle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Selector
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Page 85
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.4.3 TPM2B_NAME
+This buffer holds a Name for any entity type.
+The type of Name in the structure is determined by context and the size parameter. If size is four, then
+the Name is a handle. If size is zero, then no Name is present. Otherwise, the size shall be the size of a
+TPM_ALG_ID plus the size of the digest produced by the indicated hash algorithm.
+Table 80 — Definition of TPM2B_NAME Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the Name structure
+
+name[size]{:sizeof(TPMU_NAME)}
+
+BYTE
+
+the Name structure
+
+10.5 PCR Structures
+10.5.1 TPMS_PCR_SELECT
+This structure provides a standard method of specifying a list of PCR.
+PCR numbering starts at zero.
+PcrSelect is an array of octets. The octet containing the bit corresponding to a specific PCR is found by
+dividing the PCR number by 8.
+EXAMPLE 1
+
+The bit in pcrSelect corresponding to PCR 19 is in pcrSelect [2] (19/8 = 2).
+
+The least significant bit in a octet is bit number 0. The bit in the octet associated with a PCR is the
+remainder after division by 8.
+EXAMPLE 2
+
+The bit in pcrSelect [2] corresponding to PCR 19 is bit 3 (19 mod 8). If sizeofSelect is 3, then the
+pcrSelect array that would specify PCR 19 and no other PCR is 00 00 08 16.
+
+Each bit in pcrSelect indicates whether the corresponding PCR is selected (1) or not (0). If the pcrSelect
+is all zero bits, then no PCR is selected.
+SizeofSelect indicates the number of octets in pcrSelect. The allowable values for sizeofSelect is
+determined by the number of PCR required by the applicable platform-specific specification and the
+number of PCR implemented in the TPM. The minimum value for sizeofSelect is:
+PCR_SELECT_MIN ≔ (PLATFORM_PCR + 7) / 8
+
+(1)
+
+where
+PLATFORM_PCR
+
+the number of PCR required by the platform-specific specification
+
+The maximum value for sizeofSelect is:
+PCR_SELECT_MAX ≔ (IMPLEMENTATION_PCR + 7) / 8
+
+(2)
+
+where
+IMPLEMENTATION_PCR
+
+Page 86
+October 31, 2013
+
+the number of PCR implemented on the TPM
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+If the TPM implements more PCR than there are bits in pcrSelect, the additional PCR are not selected.
+EXAMPLE 3
+
+If the applicable platform-specific specification requires that the TPM have a minimum of 24 PCR but the
+TPM implements 32, then a PCR select of 3 octets would imply that PCR 24-31 are not selected.
+
+Table 81 — Definition of TPMS_PCR_SELECT Structure
+Parameter
+
+Type
+
+Description
+
+sizeofSelect {PCR_SELECT_MIN:}
+
+UINT8
+
+the size in octets of the pcrSelect array
+
+pcrSelect [sizeofSelect] {:PCR_SELECT_MAX}
+
+BYTE
+
+the bit map of selected PCR
+
+#TPM_RC_VALUE
+
+10.5.2 TPMS_PCR_SELECTION
+Table 82 — Definition of TPMS_PCR_SELECTION Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm associated with the
+selection
+
+sizeofSelect {PCR_SELECT_MIN:}
+
+UINT8
+
+the size in octets of the pcrSelect array
+
+pcrSelect [sizeofSelect] {:PCR_SELECT_MAX}
+
+BYTE
+
+the bit map of selected PCR
+
+#TPM_RC_VALUE
+
+10.6 Tickets
+10.6.1 Introduction
+Tickets are evidence that the TPM has previously processed some information. A ticket is an HMAC over
+the data using a secret key known only to the TPM. A ticket is a way to expand the state memory of the
+TPM. A ticket is only usable by the TPM that produced it.
+The formulations for tickets shown in this clause are to be used by a TPM that is compliant with this
+specification.
+The method of creating the ticket data is:
+
+HMACcontexAlg(proof, (ticketType || param { || param {…}))
+
+(3)
+
+where
+
+HMACcontexAlg()
+
+an HMAC using the hash used for context integrity
+
+proof
+
+a TPM secret value (depends on hierarchy)
+
+ticketType
+
+a value to differentiate the tickets
+
+param
+
+one or more values that were checked by the TPM
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 87
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+The proof value used for each hierarchy is shown in Table 83.
+Table 83 — Values for proof Used in Tickets
+Hierarchy
+
+proof
+
+Description
+
+None
+
+Empty Buffer
+
+Platform
+
+phProof
+
+a value that changes with each change of the PPS
+
+Owner
+
+shProof
+
+a value that changes with each change of the SPS
+
+Endorsement
+
+ehProof
+
+a value that changes with each change of either the EPS or SPS
+
+The format for a ticket is shown in Table 84. This is a template for the tickets shown in the remainder of
+this clause.
+Table 84 — General Format of a Ticket
+Parameter
+
+Type
+
+Description
+
+tag
+
+TPM_ST
+
+structure tag indicating the type of the ticket
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy of the proof value
+
+digest
+
+TPM2B_DIGEST
+
+the HMAC over the ticket-specific data
+
+10.6.2 A NULL Ticket
+When a command requires a ticket and no ticket is available, the caller is required to provide a structure
+with a ticket tag that is correct for the context. The hierarchy shall be set to TPM_RH_NULL, and digest
+shall be the Empty Buffer (a buffer with a size field of zero). This construct is the NULL Ticket. When a
+response indicates that a ticket is returned, the TPM may return a NULL Ticket.
+NOTE
+
+Because each use of a ticket requires that the structure tag for the ticket be appropriate for the use, t here
+is no single representation of a NULL Ticket that will work in all circumstances. Minimally, a NULL ticket
+will have a structure type that is appropriate for the context.
+
+Page 88
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.6.3 TPMT_TK_CREATION
+This ticket is produced by TPM2_Create() or TPM2_CreatePrimary(). It is used to bind the creation data
+to the object to which it applies. The ticket is computed by
+
+HMACcontextAlg(proof, (TPM_ST_CREATION || name || HnameAlg(TPMS_CREATION_DATA)))
+
+(4)
+
+where
+
+HMACcontextAlg()
+
+an HMAC using the context integrity hash algorithm
+
+proof
+
+a TPM secret value associated with the hierarchy associated with name
+
+TPM_ST_CREATION
+
+a value used to ensure that the ticket is properly used
+
+name
+
+the Name of the object to which the creation data is to be associated
+
+HnameAlg()
+
+hash using the nameAlg of the created object
+
+TPMS_CREATION_DATA the creation data structure associated with name
+Table 85 — Definition of TPMT_TK_CREATION Structure
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_CREATION}
+
+TPM_ST
+
+ticket structure tag
+error returned when tag is not TPM_ST_CREATION
+
+#TPM_RC_TAG
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy containing name
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC produced using a proof value
+of hierarchy.
+
+EXAMPLE
+
+A NULL Creation Ticket is the tuple <TPM_ST_CREATION, TPM_RH_NULL, 0x0000>.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 89
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.6.4 TPMT_TK_VERIFIED
+This ticket is produced by TPM2_VerifySignature(). This formulation is used for multiple ticket uses. The
+ticket provides evidence that the TPM has validated that a digest was signed by a key with the Name of
+keyName. The ticket is computed by
+
+HMACcontextAlg(proof, (TPM_ST_VERIFIED || digest || keyName))
+
+(5)
+
+where
+
+HMACcontextAlg()
+
+an HMAC using the context integrity hash
+
+proof
+
+a TPM secret value associated with the hierarchy associated with
+
+TPM_ST_VERIFIED
+
+a value used to ensure that the ticket is properly used
+
+digest
+
+the signed digest
+
+keyName
+
+Name of the key that signed digest
+
+keyName
+
+Table 86 — Definition of TPMT_TK_VERIFIED Structure
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_VERIFIED}
+
+TPM_ST
+
+ticket structure tag
+error returned when tag is not TPM_ST_VERIFIED
+
+#TPM_RC_TAG
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy containing keyName
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC produced using a proof value
+of hierarchy.
+
+EXAMPLE
+
+A NULL Verified Ticket is the tuple <TPM_ST_VERIFIED, TPM_RH_NULL, 0x0000>.
+
+Page 90
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.6.5 TPMT_TK_AUTH
+This ticket is produced by TPM2_PolicySigned() and TPM2_PolicySecret() when the authorization has an
+expiration time. The ticket is computed by
+
+HMACcontextAlg(proof, (TPM_ST_AUTH_xxx || timeout || cpHash || policyRef || keyName))
+
+(6)
+
+where
+
+HMACcontextAlg()
+
+an HMAC using the context integrity hash
+
+proof
+
+a TPM secret value associated with the hierarchy of the key associated
+with keyName
+
+TPM_ST_AUTH_xxx
+
+either TPM_ST_AUTH_SIGNED or TPM_ST_AUTH_SECRET; used to
+ensure that the ticket is properly used
+
+timeout
+
+implementation-specific value indicating when the authorization expires
+
+cpHash
+
+optional hash of the authorized command
+
+policyRef
+
+optional reference to a policy value
+
+keyName
+
+Name of the key that signed the authorization
+Table 87 — Definition of TPMT_TK_AUTH Structure
+
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_AUTH_SIGNED, TPM_ST_AUTH_SECRET} TPM_ST
+
+ticket structure tag
+
+#TPM_RC_TAG
+
+error returned when tag is
+not TPM_ST_AUTH
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy of the object
+used to produce the ticket
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC
+produced using a proof
+value of hierarchy.
+
+EXAMPLE
+
+A NULL Auth Ticket is the tuple <TPM_ST_AUTH_SIGNED, TPM_RH_NULL, 0x0000> or the tuple
+<TPM_ST_AUTH_SIGNED, TPM_RH_NULL, 0x0000>
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 91
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.6.6 TPMT_TK_HASHCHECK
+This ticket is produced by TPM2_SequenceComplete() when the message that was digested did not start
+with TPM_GENERATED_VALUE. The ticket is computed by
+
+HMACcontexAlg(proof, (TPM_ST_HASHCHECK || digest))
+
+(7)
+
+where
+
+HMACcontexAlg ()
+
+an HMAC using the context integrity hash
+
+proof
+
+a TPM secret value associated with the hierarchy indicated by the
+command
+
+TPM_ST_HASHCHECK
+
+a value used to ensure that the ticket is properly used
+
+digest
+
+the digest of the data
+Table 88 — Definition of TPMT_TK_HASHCHECK Structure
+
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_HASHCHECK}
+
+TPM_ST
+
+ticket structure tag
+
+#TPM_RC_TAG
+
+error returned when is not TPM_ST_HASHCHECK
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC produced using a proof value
+of hierarchy.
+
+10.7 Property Structures
+10.7.1 TPMS_ALG_PROPERTY
+This structure is used to report the properties of an algorithm identifier. It is returned in response to a
+TPM2_GetCapability() with capability = TPM_CAP_ALG.
+Table 89 — Definition of TPMS_ALG_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+alg
+
+TPM_ALG_ID
+
+an algorithm identifier
+
+algProperties
+
+TPMA_ALGORITHM
+
+the attributes of the algorithm
+
+10.7.2 TPMS_TAGGED_PROPERTY
+This structure is used to report the properties that are UINT32 values. It is returned in response to a
+TPM2_GetCapability().
+Table 90 — Definition of TPMS_TAGGED_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+property
+
+TPM_PT
+
+a property identifier
+
+value
+
+UINT32
+
+the value of the property
+
+Page 92
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.7.3 TPMS_TAGGED_PCR_SELECT
+This structure is used in TPM2_GetCapability() to return the attributes of the PCR.
+Table 91 — Definition of TPMS_TAGGED_PCR_SELECT Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+tag
+
+TPM_PT
+
+the property identifier
+
+sizeofSelect {PCR_SELECT_MIN:}
+
+UINT8
+
+the size in octets of the pcrSelect array
+
+pcrSelect [sizeofSelect] {:PCR_SELECT_MAX}
+
+BYTE
+
+the bit map of PCR with the identified property
+
+10.8 Lists
+10.8.1 TPML_CC
+A list of command codes may be input to the TPM or returned by the TPM depending on the command.
+Table 92 — Definition of TPML_CC Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of commands in the commandCode list;
+may be 0
+
+commandCodes[count]{:MAX_CAP_CC}
+
+TPM_CC
+
+a list of command codes
+The maximum only applies to a command code
+list in a command. The response size is limited
+only by the size of the parameter buffer.
+
+#TPM_RC_SIZE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+response code when count is greater than the
+maximum allowed list size
+
+Published
+Copyright © TCG 2006-2013
+
+Page 93
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.8.2 TPML_CCA
+This list is only used in TPM2_GetCapability(capability = TPM_CAP_COMMANDS).
+The values in the list are returned in commandIndex order with vendor-specific commands returned after
+other commands. Because of the other attributes, the commands may not be returned in strict numerical
+order. They will be in commandIndex order.
+Table 93 — Definition of TPML_CCA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of values in the commandAttributes list;
+may be 0
+
+commandAttributes[count]{:MAX_CAP_CC}
+
+TPMA_CC
+
+a list of command codes attributes
+
+10.8.3 TPML_ALG
+This list is returned by TPM2_IncrementalSelfTest().
+Table 94 — Definition of TPML_ALG Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of algorithms in the algorithms list; may be 0
+
+algorithms[count]{:MAX_ALG_LIST_SIZE}
+
+TPM_ALG_ID a list of algorithm IDs
+The maximum only applies to an algorithm list in a
+command. The response size is limited only by the
+size of the parameter buffer.
+response code when count is greater than the
+maximum allowed list size
+
+#TPM_RC_SIZE
+
+10.8.4 TPML_HANDLE
+This structure is used when the TPM returns a list of loaded handles when the capability in
+TPM2_GetCapability() is TPM_CAP_HANDLE.
+NOTE
+
+This list is not used as input to the TPM.
+
+Table 95 — Definition of TPML_HANDLE Structure <OUT>
+Name
+
+Type
+
+Description
+
+count
+
+UINT32
+
+the number of handles in the list
+may have a value of 0
+
+handle[count]{: MAX_CAP_HANDLES}
+
+TPM_HANDLE
+
+an array of handles
+
+#TPM_RC_SIZE
+
+Page 94
+October 31, 2013
+
+response code when count is greater than the
+maximum allowed list size
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.8.5 TPML_DIGEST
+This list is used to convey a list of digest values. This type is used in TPM2_PolicyOR() and in
+TPM2_PCR_Read().
+Table 96 — Definition of TPML_DIGEST Structure
+Parameter
+
+Type
+
+Description
+
+count {2:}
+
+UINT32
+
+number of digests in the list, minimum is two for
+TPM2_PolicyOR().
+
+digests[count]{:8}
+
+TPM2B_DIGEST a list of digests
+For TPM2_PolicyOR(), all digests will have been
+computed using the digest of the policy session. For
+TPM2_PCR_Read(), each digest will be the size of the
+digest for the bank containing the PCR.
+
+#TPM_RC_SIZE
+
+response code when count is not at least two or is
+greater than eight
+
+10.8.6 TPML_DIGEST_VALUES
+This list is used to convey a list of digest values. This type is returned by TPM2_Event() and
+TPM2_SequenceComplete() and is an input for TPM2_PCR_Extend().
+NOTE 1
+
+This construct limits the number of hashes in the list to the number of digests implemented in the TPM
+rather than the number of PCR banks. This allows extra values to appear in a call t o
+TPM2_PCR_Extend().
+
+NOTE 2
+
+The digest for an unimplemented hash algorithm may not be in a list because the TPM may not recognize
+the algorithm as being a hash and it may not know the digest size.
+
+Table 97 — Definition of TPML_DIGEST_VALUES Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of digests in the list
+
+digests[count]{:HASH_COUNT}
+
+TPMT_HA
+
+a list of tagged digests
+response code when count is greater than the possible
+number of banks
+
+#TPM_RC_SIZE
+
+10.8.7 TPM2B_DIGEST_VALUES
+Digest list in a sized buffer. This list is returned by TPM2_PCR_SequenceComplete().
+Table 98 — Definition of TPM2B_DIGEST_VALUES Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the operand buffer
+
+buffer [size] {:sizeof(TPML_DIGEST_VALUES)}
+
+BYTE
+
+the operand
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 95
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.8.8 TPML_PCR_SELECTION
+This list is used to indicate the PCR that are included in a selection when more than one PCR value may
+be selected.
+This structure is an input parameter to TPM2_PolicyPCR() to indicate the PCR that will be included in the
+digest of PCR for the authorization. The structure is used in TPM2_PCR_Read() command to indicate the
+PCR values to be returned and in the response to indicate which PCR are included in the list of returned
+digests. The structure is an output parameter from TPM2_Create() and indicates the PCR used in the
+digest of the PCR state when the object was created. The structure is also contained in the attestation
+structure of TPM2_Quote().
+When this structure is used to select PCR to be included in a digest, the selected PCR are concatenated
+to create a “message” containing all of the PCR, and then the message is hashed using the contextspecific hash algorithm.
+Table 99 — Definition of TPML_PCR_SELECTION Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of selection structures
+A value of zero is allowed.
+
+pcrSelections[count]{:HASH_COUNT}
+
+TPMS_PCR_SELECTION
+
+list of selections
+response code when count is greater
+than the possible number of banks
+
+#TPM_RC_SIZE
+
+10.8.9 TPML_ALG_PROPERTY
+This list is used to report on a list of algorithm attributes. It is returned in a TPM2_GetCapability().
+Table 100 — Definition of TPML_ALG_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of algorithm properties structures
+A value of zero is allowed.
+
+algProperties[count]{:MAX_CAP_ALGS}
+
+TPMS_ALG_PROPERTY
+
+list of properties
+
+10.8.10 TPML_TAGGED_TPM_PROPERTY
+This list is used to report on a list of properties that are TPMS_TAGGED_PROPERTY values. It is
+returned by a TPM2_GetCapability().
+Table 101 — Definition of TPML_TAGGED_TPM_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of properties
+A value of zero is allowed.
+
+tpmProperty[count]{:MAX_TPM_PROPERTIES} TPMS_TAGGED_PROPERTY
+
+Page 96
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+an array of tagged properties
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.8.11 TPML_TAGGED_PCR_PROPERTY
+This list is used to report on a list of properties that are TPMS_PCR_SELECT values. It is returned by a
+TPM2_GetCapability().
+Table 102 — Definition of TPML_TAGGED_PCR_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of properties
+A value of zero is allowed.
+
+pcrProperty[count]{:MAX_PCR_PROPERTIES}
+
+TPMS_TAGGED_PCR_SELECT a tagged PCR selection
+
+10.8.12 TPML_ECC_CURVE
+This list is used to report the ECC curve ID values supported by the TPM. It is returned by a
+TPM2_GetCapability().
+Table 103 — Definition of {ECC} TPML_ECC_CURVE Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of curves
+A value of zero is allowed.
+
+eccCurves[count]{:MAX_ECC_CURVES}
+
+TPM_ECC_CURVE
+
+array of ECC curve identifiers
+
+10.9 Capabilities Structures
+10.9.1 TPMU_CAPABILITIES
+Table 104 — Definition of TPMU_CAPABILITIES Union <OUT>
+Parameter
+
+Type
+
+Selector
+
+algorithms
+
+TPML_ALG_PROPERTY
+
+TPM_CAP_ALGS
+
+handles
+
+TPML_HANDLE
+
+TPM_CAP_HANDLES
+
+command
+
+TPML_CCA
+
+TPM_CAP_COMMANDS
+
+ppCommands
+
+TPML_CC
+
+TPM_CAP_PP_COMMANDS
+
+auditCommands
+
+TPML_CC
+
+TPM_CAP_AUDIT_COMMANDS
+
+assignedPCR
+
+TPML_PCR_SELECTION
+
+TPM_CAP_PCRS
+
+tpmProperties
+
+TPML_TAGGED_TPM_PROPERTY
+
+TPM_CAP_TPM_PROPERTIES
+
+pcrProperties
+
+TPML_TAGGED_PCR_PROPERTY
+
+TPM_CAP_PCR_PROPERTIES
+
+eccCurves
+
+TPML_ECC_CURVE
+
+TPM_CAP_ECC_CURVES
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Description
+
+TPM_ALG_ECC
+
+Page 97
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.9.2 TPMS_CAPABILITY_DATA
+This data area is returned in response to a TPM2_GetCapability().
+Table 105 — Definition of TPMS_CAPABILITY_DATA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+capability
+
+TPM_CAP
+
+the capability
+
+[capability]data
+
+TPMU_CAPABILITIES
+
+the capability data
+
+10.10 Clock/Counter Structures
+10.10.1 TPMS_CLOCK_INFO
+This structure is used in each of the attestation commands.
+Table 106 — Definition of TPMS_CLOCK_INFO Structure
+Parameter
+
+Type
+
+Description
+
+clock
+
+UINT64
+
+time in milliseconds during which the TPM has been powered
+This structure element is used to report on the TPM's Clock value.
+The value of Clock shall be recorded in non-volatile memory no
+22
+less often than once per 2 milliseconds (~69.9 minutes) of TPM
+operation. The reference for the millisecond timer is the TPM
+oscillator.
+This value is reset to zero when the Storage Primary Seed is
+changed (TPM2_Clear()).
+This value may be advanced by TPM2_AdvanceClock().
+
+resetCount
+
+UINT32
+
+number of occurrences of TPM Reset since the last TPM2_Clear()
+
+restartCount
+
+UINT32
+
+number of times that TPM2_Shutdown() or _TPM_Hash_Start have
+occurred since the last TPM Reset or TPM2_Clear().
+
+safe
+
+TPMI_YES_NO
+
+no value of Clock greater than the current value of Clock has been
+previously reported by the TPM. Set to YES on TPM2_Clear().
+
+10.10.2 Clock
+Clock is a monotonically increasing counter that advances whenever power is applied to the TPM. The
+value of Clock may be set forward with TPM2_ClockSet() if ownerAuth or platformAuth is provided. The
+value of Clock is incremented each millisecond.
+TPM2_Clear() will set Clock to zero.
+Clock will be non-volatile but may have a volatile component that is updated every millisecond with the
+non-volatile component updated at a lower rate. If the implementation uses a volatile component, the non22
+volatile component shall be updated no less frequently than every 2 milliseconds (~69.9 minutes). The
+update rate of the non-volatile portion of Clock shall be reported by a TPM2_GetCapability() with
+capability = TPM_CAP_TPM_PROPERTIES and property = TPM_PT_CLOCK_UPDATE.
+10.10.3 ResetCount
+This counter shall increment on each TPM Reset. This counter shall be reset to zero by TPM2_Clear().
+
+Page 98
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.10.4 RestartCount
+This counter shall increment by one for each TPM Restart or TPM Resume. The restartCount shall be
+reset to zero on a TPM Reset or TPM2_Clear().
+10.10.5 Safe
+This parameter is set to YES when the value reported in Clock is guaranteed to be unique for the current
+Owner. It is set to NO when the value of Clock may have been reported in a previous attestation or
+access.
+This parameter will be YES if a TPM2_Startup() was preceded by TPM2_Shutdown() with no intervening
+commands. It will also be YES after an update of the non-volatile bits of Clock have been updated at the
+end of an update interval.
+If a TPM implementation does not implement
+TPMS_CLOCK_INFO.clock shall always be zero.
+
+Clock,
+
+Safe
+
+shall
+
+always
+
+be
+
+NO
+
+and
+
+This parameter will be set to YES by TPM2_Clear().
+10.10.6 TPMS_TIME_INFO
+This structure is used in the TPM2_TICK attestation.
+The Time value reported in this structure is reset whenever the TPM is reset. An implementation may
+reset the value of Time any time after _TPM_Init and before the TPM returns after TPM2_Start(). The
+value of Time shall increment continuously while power is applied to the TPM.
+Table 107 — Definition of TPMS_TIME_INFO Structure
+Parameter
+
+Type
+
+Description
+
+time
+
+UINT64
+
+time in milliseconds since the last _TPM_Init() or TPM2_Startup()
+This structure element is used to report on the TPM's Time value.
+
+clockInfo
+
+TPMS_CLOCK_INFO
+
+a structure containing the clock information
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 99
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.11 TPM Attestation Structures
+10.11.1 Introduction
+This clause describes the structures that are used when a TPM creates a structure to be signed. The
+signing structures follow a standard format TPM2B_ATTEST with case-specific information embedded.
+10.11.2 TPMS_TIME_ATTEST_INFO
+This structure is used when the TPM performs TPM2_GetClock.
+Table 108 — Definition of TPMS_TIME_ATTEST_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+time
+
+TPMS_TIME_INFO
+
+the Time, clock, resetCount, restartCount, and Safe indicator
+
+firmwareVersion
+
+UINT64
+
+a vendor-specific value indicating the version number of the
+firmware
+
+10.11.3 TPMS_CERTIFY_INFO
+This is the attested data for TPM2_Certify().
+Table 109 — Definition of TPMS_CERTIFY_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+name
+
+TPM2B_NAME
+
+Name of the certified object
+
+qualifiedName
+
+TPM2B_NAME
+
+Qualified Name of the certified object
+
+10.11.1 TPMS_QUOTE_INFO
+This is the attested data for TPM2_Quote().
+Table 110 — Definition of TPMS_QUOTE_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+pcrSelect
+
+TPML_PCR_SELECTION
+
+information on algID, PCR selected and digest
+
+pcrDigest
+
+TPM2B_DIGEST
+
+digest of the selected PCR using the hash of the signing key
+
+Page 100
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.11.2 TPMS_COMMAND_AUDIT_INFO
+This is the attested data for TPM2_GetCommandAuditDigest().
+Table 111 — Definition of TPMS_COMMAND_AUDIT_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+auditCounter
+
+UINT64
+
+the monotonic audit counter
+
+digestAlg
+
+TPM_ALG_ID
+
+hash algorithm used for the command audit
+
+auditDigest
+
+TPM2B_DIGEST
+
+the current value of the audit digest
+
+commandDigest
+
+TPM2B_DIGEST
+
+digest of the command codes being audited using digestAlg
+
+10.11.3 TPMS_SESSION_AUDIT_INFO
+This is the attested data for TPM2_GetSessionAuditDigest().
+Table 112 — Definition of TPMS_SESSION_AUDIT_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+exclusiveSession
+
+TPMI_YES_NO
+
+current exclusive status of the session
+TRUE if all of the commands recorded in the sessionDigest were
+executed without any intervening TPM command that did not use
+this transport session
+
+sessionDigest
+
+TPM2B_DIGEST
+
+the current value of the session audit digest
+
+10.11.4 TPMS_CREATION_INFO
+This is the attested data for TPM2_CertifyCreation().
+Table 113 — Definition of TPMS_CREATION_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+objectName
+
+TPM2B_NAME
+
+Name of the object
+
+creationHash
+
+TPM2B_DIGEST
+
+creationHash
+
+10.11.5 TPMS_NV_CERTIFY_INFO
+This structure contains the Name and contents of the selected NV Index that is certified by
+TPM2_NV_Certify().
+Table 114 — Definition of TPMS_NV_CERTIFY_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+indexName
+
+TPM2B_NAME
+
+Name of the NV Index
+
+offset
+
+UINT16
+
+the offset parameter of TPM2_NV_Certify()
+
+nvContents
+
+TPM2B_MAX_NV_BUFFER
+
+contents of the NV Index
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 101
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.11.6 TPMI_ST_ATTEST
+Table 115 — Definition of (TPM_ST) TPMI_ST_ATTEST Type <OUT>
+Value
+
+Description
+
+TPM_ST_ATTEST_CERTIFY
+
+generated by TPM2_Certify()
+
+TPM_ST_ATTEST_QUOTE
+
+generated by TPM2_Quote()
+
+TPM_ST_ATTEST_SESSION_AUDIT
+
+generated by TPM2_GetSessionAuditDigest()
+
+TPM_ST_ATTEST_COMMAND_AUDIT
+
+generated by TPM2_GetCommandAuditDigest()
+
+TPM_ST_ATTEST_TIME
+
+generated by TPM2_GetTime()
+
+TPM_ST_ATTEST_CREATION
+
+generated by TPM2_CertifyCreation()
+
+TPM_ST_ATTEST_NV
+
+generated by TPM2_NV_Certify()
+
+10.11.7 TPMU_ATTEST
+Table 116 — Definition of TPMU_ATTEST Union <OUT>
+Parameter
+
+Type
+
+Selector
+
+certify
+
+TPMS_CERTIFY_INFO
+
+TPM_ST_ATTEST_CERTIFY
+
+creation
+
+TPMS_CREATION_INFO
+
+TPM_ST_ATTEST_CREATION
+
+quote
+
+TPMS_QUOTE_INFO
+
+TPM_ST_ATTEST_QUOTE
+
+commandAudit
+
+TPMS_COMMAND_AUDIT_INFO TPM_ST_ATTEST_COMMAND_AUDIT
+
+sessionAudit
+
+TPMS_SESSION_AUDIT_INFO
+
+TPM_ST_ATTEST_SESSION_AUDIT
+
+time
+
+TPMS_TIME_ATTEST_INFO
+
+TPM_ST_ATTEST_TIME
+
+nv
+
+TPMS_NV_CERTIFY_INFO
+
+TPM_ST_ATTEST_NV
+
+Page 102
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.11.8 TPMS_ATTEST
+This structure is used on each TPM-generated signed structure. The signature is over this structure.
+When the structure is signed by a key in the Storage hierarchy, the values of clockInfo.resetCount,
+clockInfo.restartCount, and firmwareVersion are obfuscated with a per-key obfuscation value.
+Table 117 — Definition of TPMS_ATTEST Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+magic
+
+TPM_GENERATED
+
+the indication that this structure was created by a TPM (always
+TPM_GENERATED_VALUE)
+
+type
+
+TPMI_ST_ATTEST
+
+type of the attestation structure
+
+qualifiedSigner
+
+TPM2B_NAME
+
+Qualified Name of the signing key
+
+extraData
+
+TPM2B_DATA
+
+external information supplied by caller
+NOTE
+
+A TPM2B_DATA structure provides room for a digest and a
+method indicator to indicate the components of the digest.
+The definition of this method indicator is outside the scope
+of this specification.
+
+clockInfo
+
+TPMS_CLOCK_INFO
+
+Clock, resetCount, restartCount, and Safe
+
+firmwareVersion
+
+UINT64
+
+TPM-vendor-specific field identifying the firmware on the TPM
+
+[type]attested
+
+TPMU_ATTEST
+
+the type-specific attestation information
+
+10.11.9 TPM2B_ATTEST
+This sized buffer to contain the signed structure. The attestationData is the signed portion of the structure.
+The size parameter is not signed.
+Table 118 — Definition of TPM2B_ATTEST Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the attestationData structure
+
+attestationData[size]{:sizeof(TPMS_ATTEST)}
+
+BYTE
+
+the signed structure
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 103
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.12 Authorization Structures
+The structures in this clause are used for all authorizations. One or more of these structures will be
+present in a command or response that has a tag of TPM_ST_SESSIONS.
+10.12.1 TPMS_AUTH_COMMAND
+This is the format used for each of the authorizations in the session area of a command.
+Table 119 — Definition of TPMS_AUTH_COMMAND Structure <IN>
+Parameter
+
+Type
+
+Description
+
+sessionHandle
+
+TPMI_SH_AUTH_SESSION+
+
+the session handle
+
+nonce
+
+TPM2B_NONCE
+
+the session nonce, may be the Empty Buffer
+
+sessionAttributes
+
+TPMA_SESSION
+
+the session attributes
+
+hmac
+
+TPM2B_AUTH
+
+either an HMAC, a password, or an EmptyAuth
+
+10.12.2 TPMS_AUTH_RESPONSE
+This is the format for each of the authorizations in the session area of the response. If the TPM returns
+TPM_RC_SUCCESS, then the session area of the response contains the same number of authorizations
+as the command and the authorizations are in the same order.
+Table 120 — Definition of TPMS_AUTH_RESPONSE Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+nonce
+
+TPM2B_NONCE
+
+the session nonce, may be the Empty Buffer
+
+sessionAttributes
+
+TPMA_SESSION
+
+the session attributes
+
+hmac
+
+TPM2B_AUTH
+
+either an HMAC, a password, or an EmptyAuth
+
+Page 104
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11 Algorithm Parameters and Structures
+11.1 Symmetric
+11.1.1 Introduction
+This clause defines the parameters and structures for describing symmetric algorithms.
+11.1.2 TPMI_AES_KEY_BITS
+This interface type defines the supported sizes for an AES key. This type is used to allow the
+unmarshaling routine to generate the proper validation code for the supported key sizes. An
+implementation that supports different key sizes would have a different set of selections.
+When used in TPM2_StartAuthSession(), the mode parameter shall be TPM_ALG_CFB.
+NOTE 1
+
+Key size is expressed in bits.
+
+NOTE 2
+
+The definition for AES_KEY_SIZES_BITS used in the reference implementation is found in Annex B
+
+Table 121 — Definition of {AES} (TPM_KEY_BITS) TPMI_AES_KEY_BITS Type
+Parameter
+
+Description
+
+$AES_KEY_SIZES_BITS
+
+number of bits in the key
+
+#TPM_RC_VALUE
+
+error when key size is not supported
+
+11.1.3 TPMI_SM4_KEY_BITS
+This interface type defines the supported sizes for an SM4 key. This type is used to allow the
+unmarshaling routine to generate the proper validation code for the supported key sizes. An
+implementation that supports different key sizes would have a different set of selections.
+NOTE
+
+SM4 only supports a key size of 128 bits.
+
+Table 122 — Definition of {SM4} (TPM_KEY_BITS) TPMI_SM4_KEY_BITS Type
+Parameter
+
+Description
+
+$SM4_KEY_SIZES_BITS
+
+number of bits in the key
+
+#TPM_RC_VALUE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 105
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.1.4 TPMU_SYM_KEY_BITS
+This union is used to collect the symmetric encryption key sizes.
+The xor entry is a hash algorithms selector and not a key size in bits. This overload is used in order to
+avoid an additional level of indirection with another union and another set of selectors.
+The xor entry is only selected in a TPMT_SYM_DEF, which is used to select the parameter encryption
+value.
+Table 123 — Definition of TPMU_SYM_KEY_BITS Union
+Parameter
+
+Type
+
+Selector
+
+aes
+
+TPMI_AES_KEY_BITS
+
+TPM_ALG_AES
+
+SM4
+
+TPMI_SM4_KEY_BITS
+
+TPM_ALG_SM4
+
+sym
+
+TPM_KEY_BITS
+
+xor
+
+TPMI_ALG_HASH
+
+Description
+
+when selector may be any of the
+symmetric block ciphers
+TPM_ALG_XOR
+
+overload for using xor
+NOTE
+
+null
+
+TPM_ALG_NULL
+allowed
+
+is
+
+not
+
+TPM_ALG_NULL
+
+11.1.5 TPMU_SYM_MODE
+This union allows the mode value in a TPMT_SYM_DEF or TPMT_SYM_DEF_OBJECT to be empty.
+Table 124 — Definition of TPMU_SYM_MODE Union
+Parameter
+
+Type
+
+Selector
+
+Description
+
+aes
+
+TPMI_ALG_SYM_MODE
+
+TPM_ALG_AES
+
+NOTE
+
+TPM_ALG_NULL
+allowed
+
+is
+
+not
+
+SM4
+
+TPMI_ALG_SYM_MODE
+
+TPM_ALG_SM4
+
+NOTE
+
+TPM_ALG_NULL
+allowed
+
+is
+
+not
+
+sym
+
+TPMI_ALG_SYM_MODE
+
+when selector may be any of the
+symmetric block ciphers
+
+xor
+
+TPM_ALG_XOR
+
+no mode selector
+
+null
+
+TPM_ALG_NULL
+
+no mode selector
+
+Page 106
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.6 TPMU_SYM_DETAILS
+This union allows additional parameters to be added for a symmetric cipher. Currently, no additional
+parameters are required for any of the symmetric algorithms.
+NOTE
+
+The “x” character in the table title will suppress generation of this type as the parser is not, at this time,
+able to generate the proper values (a union of all empty data types). When an algorithm is added that
+requires additional parameterization, the Type column will contain a value and the “x” may be removed.
+
+Table 125 — xDefinition of TPMU_SYM_DETAILS Union
+Parameter
+
+Type
+
+Selector
+
+aes
+
+TPM_ALG_AES
+
+SM4
+
+Description
+
+TPM_ALG_SM4
+
+sym
+
+when selector may be any of the
+symmetric block ciphers
+
+xor
+
+TPM_ALG_XOR
+
+null
+
+TPM_ALG_NULL
+
+11.1.7 TPMT_SYM_DEF
+The TPMT_SYM_DEF structure is used to select an algorithm to be used for parameter encryption in
+those cases when different symmetric algorithms may be selected.
+Table 126 — Definition of TPMT_SYM_DEF Structure
+Parameter
+
+Type
+
+Description
+
+algorithm
+
++TPMI_ALG_SYM
+
+indicates a symmetric algorithm
+
+[algorithm]keyBits
+
+TPMU_SYM_KEY_BITS
+
+a supported key size
+
+[algorithm]mode
+
+TPMU_SYM_MODE
+
+the mode for the key
+
+//[algorithm]details
+
+TPMU_SYM_DETAILS
+
+contains additional algorithm details
+NOTE
+
+This is commented out at this time as the parser
+may not produce the proper code for a union if
+none of the selectors produces any data.
+
+11.1.8 TPMT_SYM_DEF_OBJECT
+This structure is used when different symmetric block cipher (not XOR) algorithms may be selected.
+Table 127 — Definition of TPMT_SYM_DEF_OBJECT Structure
+Parameter
+
+Type
+
+Description
+
+algorithm
+
++TPMI_ALG_SYM_OBJECT
+
+selects a symmetric block cipher
+
+[algorithm]keyBits
+
+TPMU_SYM_KEY_BITS
+
+the key size
+
+[algorithm]mode
+
+TPMU_SYM_MODE
+
+default mode
+
+//[algorithm]details
+
+TPMU_SYM_DETAILS
+
+contains the additional algorithm details, if any
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+This is commented out at this time as the parser
+may not produce the proper code for a union if
+none of the selectors produces any data.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 107
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.1.9 TPM2B_SYM_KEY
+This structure is used to hold a symmetric key in the sensitive area of an asymmetric object.
+The number of bits in the key is in keyBits in the public area. When keyBits is not an even multiple of 8
+bits, the unused bits of buffer will be the most significant bits of buffer[0] and size will be rounded up to
+the number of octets required to hold all bits of the key.
+Table 128 — Definition of TPM2B_SYM_KEY Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size, in octets, of the buffer containing the key; may be
+zero
+
+buffer [size] {:MAX_SYM_KEY_BYTES}
+
+BYTE
+
+the key
+
+11.1.10 TPMS_SYMCIPHER_PARMS
+This structure contains the parameters for a symmetric block cipher object.
+Table 129 — Definition of TPMS_SYMCIPHER_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+sym
+
+TPMT_SYM_DEF_OBJECT
+
+a symmetric block cipher
+
+11.1.11 TPM2B_SENSITIVE_DATA
+This buffer holds the secret data of a data object. It can hold as much as 128 octets of data.
+MAX_SYM_DATA shall be 128.
+NOTE
+
+A named value rather than a numeric is used to make coding clearer. A numeric value does not indicate
+the reason that it has the specific value that is has.
+
+Table 130 — Definition of TPM2B_SENSITIVE_DATA Structure
+Parameter
+
+Type
+
+size
+
+UINT16
+
+buffer[size]{: MAX_SYM_DATA}
+
+BYTE
+
+Page 108
+October 31, 2013
+
+Description
+
+the keyed hash private data structure
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.12 TPMS_SENSITIVE_CREATE
+This structure defines the values to be placed in the sensitive area of a created object. This structure is
+only used within a TPM2B_SENSITIVE_CREATE structure.
+NOTE
+
+When sent to the TPM or unsealed, data is usually encrypted using parameter encryption.
+
+If data.size is not zero, and the object is not a keyedHash, data.size must match the size indicated in the
+keySize of public.parameters. If the object is a keyedHash, data.size may be any value up to the
+maximum allowed in a TPM2B_SENSITIVE_DATA.
+For an asymmetric object, data shall be an Empty Buffer and sensitiveDataOrigin shall be SET.
+Table 131 — Definition of TPMS_SENSITIVE_CREATE Structure <IN>
+Parameter
+
+Type
+
+Description
+
+userAuth
+
+TPM2B_AUTH
+
+the USER auth secret value
+
+data
+
+TPM2B_SENSITIVE_DATA
+
+data to be sealed
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 109
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.1.13 TPM2B_SENSITIVE_CREATE
+This structure contains the sensitive creation data in a sized buffer. This structure is defined so that both
+the userAuth and data values of the TPMS_SENSITIVE_CREATE may be passed as a single parameter
+for parameter encryption purposes.
+Table 132 — Definition of TPM2B_SENSITIVE_CREATE Structure <IN, S>
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of sensitive in octets (may not be zero)
+NOTE
+
+sensitive
+
+TPMS_SENSITIVE_CREATE
+
+The userAuth and data parameters in this buffer
+may both be zero length but the minimum size of
+this parameter will be the sum of the size fields of
+the
+two
+parameters
+of
+the
+TPMS_SENSITIVE_CREATE.
+
+data to be sealed or a symmetric key value.
+
+11.1.14 TPMS_SCHEME_SIGHASH
+This structure is the scheme data for schemes that only require a hash to complete the scheme definition.
+Table 133 — Definition of TPMS_SCHEME_SIGHASH Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+11.1.15 TPMI_ALG_HASH_SCHEME
+This is the list of values that may appear in a keyedHash as the scheme parameter.
+Table 134 — Definition of (TPM_ALG_ID) TPMI_ALG_KEYEDHASH_SCHEME Type
+Values
+
+Comments
+
+TPM_ALG_HMAC
+
+the "signing" scheme
+
+TPM_ALG_XOR
+
+the "obfuscation" scheme
+
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.1.16 HMAC_SIG_SCHEME
+Table 135 — Definition of Types for HMAC_SIG_SCHEME
+Type
+
+Name
+
+TPMS_SCHEME_SIGHASH
+
+TPMS_SCHEME_HMAC
+
+Page 110
+October 31, 2013
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.17 TPMS_SCHEME_XOR
+This structure is for the XOR encryption scheme.
+Table 136 — Definition of TPMS_SCHEME_XOR Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+kdf
+
+TPMI_ALG_KDF
+
+the key derivation function
+
+11.1.18 TPMU_SCHEME_HMAC
+Table 137 — Definition of TPMU_SCHEME_KEYEDHASH Union <IN/OUT, S>
+Parameter
+
+Type
+
+Selector
+
+Description
+
+hmac
+
+TPMS_SCHEME_HMAC
+
+TPM_ALG_HMAC
+
+the "signing" scheme
+
+xor
+
+TPMS_SCHEME_XOR
+
+TPM_ALG_XOR
+
+the "obfuscation" scheme
+
+null
+
+TPM_ALG_NULL
+
+11.1.19 TPMT_KEYEDHASH_SCHEME
+This structure is used for a hash signing object.
+Table 138 — Definition of TPMT_KEYEDHASH_SCHEME Structure
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_KEYEDHASH_SCHEME
+
+selects the scheme
+
+[scheme]details
+
+TPMU_SCHEME_KEYEDHASH
+
+the scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 111
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.2 Asymmetric
+11.2.1 Signing Schemes
+11.2.1.1
+
+Introduction
+
+These structures are used to define the method in which the signature is to be created. These schemes
+would appear in an object’s public area and in commands where the signing scheme is variable.
+Every scheme is required to indicate a hash that is used in digesting the message.
+11.2.1.2
+
+RSA_SIG_SCHEMES
+
+These are the RSA schemes that only need a hash algorithm as a scheme parameter.
+For the TPM_ALG_RSAPSS signing scheme, the same hash algorithm is used for digesting TPMgenerated data (an attestation structure) and in the KDF used for the masking operation. The salt size is
+always the largest salt value that will fit into the available space.
+Table 139 — Definition of {RSA} Types for RSA_SIG_SCHEMES
+Type
+
+Name
+
+Description
+
+TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSASSA
+TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSAPSS
+
+11.2.1.3
+
+ECC_SIG_SCHEMES
+
+These are the ECC schemes that only need a hash algorithm as a controlling parameter.
+Table 140 — Definition of {ECC} Types for ECC_SIG_SCHEMES
+Type
+
+Name
+
+Description
+
+TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECDSA
+TPMS_SCHEME_SIGHASH TPMS_SCHEME_SM2
+TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECSCHNORR
+
+11.2.1.4 TPMS_SCHEME_ECDAA
+Table 141 — Definition of {ECC} TPMS_SCHEME_ECDAA Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+count
+
+UINT16
+
+the counter value that is used between TPM2_Commit() and the sign
+operation
+
+Page 112
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+11.2.1.5
+
+Part 2: Structures
+
+TPMU_SIG_SCHEME
+Table 142 — Definition of TPMU_SIG_SCHEME Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsassa
+
+TPMS_SCHEME_RSASSA
+
+TPM_ALG_RSASSA
+
+the PKCS#1v1.5 scheme
+
+rsapss
+
+TPMS_SCHEME_RSAPSS
+
+TPM_ALG_RSAPSS
+
+the PKCS#1v2.1 PSS scheme
+
+ecdsa
+
+TPMS_SCHEME_ECDSA
+
+TPM_ALG_ECDSA
+
+the ECDSA scheme
+
+sm2
+
+TPMS_SCHEME_SM2
+
+TPM_ALG_SM2
+
+ECDSA from SM2
+
+ecdaa
+
+TPMS_SCHEME_ECDAA
+
+TPM_ALG_ECDAA
+
+the ECDAA scheme
+
+ecSchnorr
+
+TPMS_SCHEME_ECSCHNORR
+
+TPM_ALG_ECSCHNORR
+
+the EC Schnorr
+
+hmac
+
+TPMS_SCHEME_HMAC
+
+TPM_ALG_HMAC
+
+the HMAC scheme
+
+any
+
+TPMS_SCHEME_SIGHASH
+
+null
+
+11.2.1.6
+
+selector that allows access to
+digest for any signing scheme
+TPM_ALG_NULL
+
+no scheme or default
+
+TPMT_SIG_SCHEME
+Table 143 — Definition of TPMT_SIG_SCHEME Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_SIG_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_SIG_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 113
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.2.2 Encryption Schemes
+11.2.2.1
+
+Introduction
+
+These structures are used to indicate the hash algorithm used for the encrypting process. These
+schemes would appear in an object’s public area.
+11.2.2.2
+
+TPMS_SCHEME_OAEP
+Table 144 — Definition of {RSA} TPMS_SCHEME_OAEP Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+11.2.2.3
+
+TPMS_SCHEME_ECDH
+
+For ECDH, KDFe is used for the key derivation function that only a hash algorithm is needed to complete
+the definition.
+Table 145 — Definition of {ECC} TPMS_SCHEME_ECDH Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3 Key Derivation Schemes
+11.2.3.1
+
+Introduction
+
+These structures are used to define the key derivation for symmetric secret sharing using asymmetric
+methods. A secret shareing scheme is required in any asymmetric key with the decrypt attribute SET.
+These schemes would appear in an object’s public area and in commands where the secret sharing
+scheme is variable.
+Each scheme includes a symmetric algorithm and a KDF selection.
+11.2.3.2
+
+TPMS_SCHEME_MGF1
+Table 146 — Definition of TPMS_SCHEME_MGF1 Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3.3
+
+TPMS_SCHEME_KDF1_SP800_56a
+Table 147 — Definition of {ECC} TPMS_SCHEME_KDF1_SP800_56a Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+Page 114
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+11.2.3.4
+
+Part 2: Structures
+
+TPMS_SCHEME_KDF2
+Table 148 — Definition of TPMS_SCHEME_KDF2 Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3.5
+
+TPMS_SCHEME_KDF1_SP800_108
+Table 149 — Definition of TPMS_SCHEME_KDF1_SP800_108 Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3.6
+
+TPMU_KDF_SCHEME
+Table 150 — Definition of TPMU_KDF_SCHEME Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+mgf1
+
+TPMS_SCHEME_MGF1
+
+TPM_ALG_MGF1
+
+kdf1_SP800_56a TPMS_SCHEME_KDF1_SP800_56a
+
+TPM_ALG_KDF1_SP800_56a
+
+kdf2
+
+TPMS_SCHEME_KDF2
+
+TPM_ALG_KDF2
+
+kdf1_sp800_108
+
+TPMS_SCHEME_KDF1_SP800_108
+
+Description
+
+TPM_ALG_KDF1_SP800_108
+
+null
+
+11.2.3.7
+
+TPM_ALG_NULL
+
+TPMT_KDF_SCHEME
+Table 151 — Definition of TPMT_KDF_SCHEME Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_KDF
+
+scheme selector
+
+[scheme]details
+
+TPMU_KDF_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 115
+October 31, 2013
+
+ Part 2: Structures
+11.2.3.8
+
+Trusted Platform Module Library
+
+TPMI_ALG_ASYM_SCHEME
+
+List of all of the scheme types for any asymmetric algorithm. This is used to define the
+TPMT_ASYM_SCHEME.
+Table 152 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM_SCHEME Type <>
+Values
+
+Comments
+
+TPM_ALG_RSASSA
+
+list of the allowed values
+
+TPM_ALG_RSAPSS
+TPM_ALG_RSAES
+TPM_ALG_OAEP
+TPM_ALG_ECDSA
+TPM_ALG_SM2
+TPM_ALG_ECDAA
+TPM_ALG_ECDH
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.2.3.9
+
+TPMU_ASYM_SCHEME
+
+This union of all asymmetric schemes is used in each of the asymmetric scheme structures. The actual
+scheme structure is defined by the interface type used for the selector.
+EXAMPLE
+
+The TPMT_RSA_SCHEME structure uses the TPMU_ASYM_SCHEME union but the selector type is
+TPMI_ALG_RSA_SCHEME. This means that the only elements of the union that can be selected for th e
+TPMT_RSA_SCHEME are those that are in TPMI_RSA_SCHEME.
+
+Table 153 — Definition of TPMU_ASYM_SCHEME Union
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsassa
+
+TPMS_SCHEME_RSASSA
+
+TPM_ALG_RSASSA
+
+the PKCS#1v1.5 scheme
+
+rsapss
+
+TPMS_SCHEME_RSAPSS
+
+TPM_ALG_RSAPSS
+
+the PKCS#1v2.1 PSS scheme
+
+TPM_ALG_RSAES
+
+the PKCS#1v2.1 RSAES scheme
+
+rsaes
+oaep
+
+TPMS_SCHEME_OAEP
+
+TPM_ALG_OAEP
+
+the PKSC#1v2.1 OAEP scheme
+
+ecdsa
+
+TPMS_SCHEME_ECDSA
+
+TPM_ALG_ECDSA
+
+an ECDSA scheme
+
+sm2
+
+TPMS_SCHEME_SM2
+
+TPM_ALG_SM2
+
+sign or key exchange from SM2
+
+ecdaa
+
+TPMS_SCHEME_ECDAA
+
+TPM_ALG_ECDAA
+
+an ECDAA scheme
+
+ecSchnorr
+
+TPMS_SCHEME_ECSCHNORR
+
+TPM_ALG_ECSCHNORR elliptic curve Schnorr signature
+
+ecdh
+anySig
+
+TPM_ALG_ECDH
+TPMS_SCHEME_SIGHASH
+
+null
+
+Page 116
+October 31, 2013
+
+TPM_ALG_NULL
+
+Published
+Copyright © TCG 2006-2013
+
+no scheme or default
+This selects the NULL Signature.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.2.3.10 TPMT_ASYM_SCHEME
+This structure is defined to allow overlay of all of the schemes for any asymmetric object. This structure is
+not sent on the interface.
+Table 154 — Definition of TPMT_ASYM_SCHEME Structure <>
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_ASYM_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_ASYM_SCHEME
+
+scheme parameters
+
+11.2.4 RSA
+11.2.4.1
+
+TPMI_ALG_RSA_SCHEME
+
+The list of values that may appear in the scheme parameter of a TPMS_RSA_PARMS structure.
+Table 155 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_SCHEME Type
+Values
+
+Comments
+
+TPM_ALG_RSASSA
+
+list of the allowed values
+
+TPM_ALG_RSAPSS
+TPM_ALG_RSAES
+TPM_ALG_OAEP
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.2.4.2
+
+TPMT_RSA_SCHEME
+Table 156 — Definition of {RSA} TPMT_RSA_SCHEME Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_RSA_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_ASYM_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 117
+October 31, 2013
+
+ Part 2: Structures
+11.2.4.3
+
+Trusted Platform Module Library
+
+TPMI_ALG_RSA_DECRYPT
+
+The list of values that are allowed in a decryption scheme selection as used in TPM2_RSA_Encrypt() and
+TPM2_RSA_Decrypt().
+Table 157 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_DECRYPT Type
+Values
+
+Comments
+
+TPM_ALG_RSAES
+TPM_ALG_OAEP
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.2.4.4
+
+TPMT_RSA_DECRYPT
+Table 158 — Definition of {RSA} TPMT_RSA_DECRYPT Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_RSA_DECRYPT
+
+scheme selector
+
+[scheme]details
+
+TPMU_ASYM_SCHEME
+
+scheme parameters
+
+11.2.4.5
+
+TPM2B_PUBLIC_KEY_RSA
+
+This sized buffer holds the largest RSA public key supported by the TPM.
+NOTE
+
+The reference implementation only supports key sizes of 1,024 and 2,048 bits.
+
+Table 159 — Definition of {RSA} TPM2B_PUBLIC_KEY_RSA Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the buffer
+The value of zero is only valid for create.
+
+buffer[size] {: MAX_RSA_KEY_BYTES}
+
+BYTE
+
+Value
+
+11.2.4.6
+
+TPMI_RSA_KEY_BITS
+
+This holds the value that is the maximum size allowed for an RSA key.
+NOTE 1
+
+An implementation is allowed to provide limited support for smaller RSA key sizes. That is, a TPM may be
+able to accept a smaller RSA key size in TPM2_LoadExternal() when only the public area is loaded but
+not accept that smaller key size in any command that loads both the public and private portions of an RSA
+key. This would allow the TPM to validate signatures using the smaller key but would prevent the TPM
+from using the smaller key size for any other purpose.
+
+NOTE 2
+
+The definition for RSA_KEY_SIZES_BITS used in the reference implementation is found in Annex B
+
+Page 118
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 160 — Definition of {RSA} (TPM_KEY_BITS) TPMI_RSA_KEY_BITS Type
+Parameter
+
+Description
+
+$RSA_KEY_SIZES_BITS
+
+the number of bits in the supported key
+
+#TPM_RC_VALUE
+
+error when key size is not supported
+
+11.2.4.7
+
+TPM2B_PRIVATE_KEY_RSA
+
+This sized buffer holds the largest RSA prime number supported by the TPM.
+NOTE
+
+All primes are required to have exactly half the number of significant bits as the public modulus , and the
+square of each prime is required to have the same number of significant bits as the public modulus.
+
+Table 161 — Definition of {RSA} TPM2B_PRIVATE_KEY_RSA Structure
+Parameter
+
+Type
+
+size
+
+UINT16
+
+buffer[size]{:MAX_RSA_KEY_BYTES/2}
+
+BYTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Page 119
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.2.5 ECC
+11.2.5.1
+
+TPM2B_ECC_PARAMETER
+
+This sized buffer holds the largest ECC parameter (coordinate) supported by the TPM.
+Table 162 — Definition of {ECC} TPM2B_ECC_PARAMETER Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of buffer
+
+buffer[size] {:MAX_ECC_KEY_BYTES}
+
+BYTE
+
+the parameter data
+
+11.2.5.2
+
+TPMS_ECC_POINT
+
+This structure holds two ECC coordinates that, together, make up an ECC point.
+Table 163 — Definition of {ECC} TPMS_ECC_POINT Structure
+Parameter
+
+Type
+
+Description
+
+x
+
+TPM2B_ECC_PARAMETER
+
+X coordinate
+
+y
+
+TPM2B_ECC_PARAMETER
+
+Y coordinate
+
+11.2.5.3
+
+TPM2B_ECC_POINT
+
+This structure is defined to allow a point to be a single sized parameter so that it may be encrypted.
+NOTE
+
+If the point is to be omitted, the X and Y coordinates need to be individual ly set to Empty Buffers. The
+minimum value for size will be four. It is checked indirectly by unmarshaling of the TPMS_ECC_POINT. If
+the type of point were BYTE, then size could have been zero. However, this would complicate the process
+of marshaling the structure.
+
+Table 164 — Definition of {ECC} TPM2B_ECC_POINT Structure
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of the remainder of this structure
+
+point
+
+TPMS_ECC_POINT
+
+coordinates
+error returned if the unmarshaled size of point is
+not exactly equal to size
+
+#TPM_RC_SIZE
+
+Page 120
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+11.2.5.4
+
+Part 2: Structures
+
+TPMI_ALG_ECC_SCHEME
+Table 165 — Definition of (TPM_ALG_ID) {ECC} TPMI_ALG_ECC_SCHEME Type
+
+Values
+
+Comments
+
+TPM_ALG_ECDSA
+
+these are the selections allowed for an ECC key
+
+TPM_ALG_SM2
+TPM_ALG_ECDAA
+TPM_ALG_ECSCHNORR
+TPM_ALG_ECDH
++TPM_ALG_NULL
+#TPM_RC_SCHEME
+
+11.2.5.5
+
+TPMI_ECC_CURVE
+
+The ECC curves implemented by the TPM.
+NOTE
+
+The definition of ECC_CURVES used in the reference implementation is found in Annex B
+
+Table 166 — Definition of {ECC} (TPM_ECC_CURVE) TPMI_ECC_CURVE Type
+Parameter
+
+Description
+
+$ECC_CURVES
+
+the list of implemented curves
+
+#TPM_RC_CURVE
+
+error when curve is not supported
+
+11.2.5.6
+
+TPMT_ECC_SCHEME
+
+Table 167 — Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_ECC_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_SIG_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 121
+October 31, 2013
+
+ Part 2: Structures
+11.2.5.7
+
+Trusted Platform Module Library
+
+TPMS_ALGORITHM_DETAIL_ECC
+
+This structure is used to report on the curve parameters of an ECC curve. It is returned by
+TPM2_ECC_Parameters().
+Table 168 — Definition of {ECC} TPMS_ALGORITHM_DETAIL_ECC Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+curveID
+
+TPM_ECC_CURVE
+
+identifier for the curve
+
+keySize
+
+UINT16
+
+Size in bits of the key
+
+kdf
+
+TPMT_KDF_SCHEME
+
+the default KDF and hash algorithm used in secret sharing
+operations
+
+sign
+
+TPMT_ECC_SCHEME+
+
+If not TPM_ALG_NULL, this is the mandatory signature
+scheme that is required to be used with this curve.
+
+p
+
+TPM2B_ECC_PARAMETER
+
+Fp (the modulus)
+
+a
+
+TPM2B_ECC_PARAMETER
+
+coefficient of the linear term in the curve equation
+
+b
+
+TPM2B_ECC_PARAMETER
+
+constant term for curve equation
+
+gX
+
+TPM2B_ECC_PARAMETER
+
+x coordinate of base point G
+
+gY
+
+TPM2B_ECC_PARAMETER
+
+y coordinate of base point G
+
+n
+
+TPM2B_ECC_PARAMETER
+
+order of G
+
+h
+
+TPM2B_ECC_PARAMETER
+
+cofactor (a size of zero indicates a cofactor of 1)
+
+11.3 Signatures
+11.3.1 TPMS_SIGNATURE_RSASSA
+Table 169 — Definition of {RSA} TPMS_SIGNATURE_RSASSA Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+TPM_ALG_NULL is not allowed.
+
+sig
+
+TPM2B_PUBLIC_KEY_RSA
+
+The signature is the size of a public key.
+
+11.3.2 TPMS_SIGNATURE_RSAPSS
+When the TPM generates a PSS signature, the salt size is the largest size allowed by the key and hash
+combination.
+EXAMPLE
+
+For a 2,048-bit public modulus key and SHA1 hash, the salt size is 256 – 20 – 2 = 234 octets.
+
+NOTE
+
+While this is significantly larger than required from a securit y perspective, it avoids issues of whether a
+particular size of salt value is sufficient.
+
+Page 122
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 170 — Definition of {RSA} TPMS_SIGNATURE_RSAPSS Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the signature process
+TPM_ALG_NULL is not allowed.
+
+sig
+
+TPM2B_PUBLIC_KEY_RSA
+
+The signature is the size of a public key.
+
+11.3.3 TPMS_SIGNATURE_ECDSA
+Table 171 — Definition of {ECC} TPMS_SIGNATURE_ECDSA Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the signature process
+TPM_ALG_NULL is not allowed.
+
+signatureR
+
+TPM2B_ECC_PARAMETER
+
+signatureS
+
+TPM2B_ECC_PARAMETER
+
+11.3.4 TPMU_SIGNATURE
+A TPMU_SIGNATURE_COMPOSITE is a union of the various signatures that is supported by a particular
+TPM implementation. The union allows substitution of any signature algorithm wherever a signature is
+required in a structure. Table 172 is an illustration of a TPMU_SIGNATURE for a TPM that implements
+both RSA and ECC signing.
+NOTE 1
+
+All TPM are required to support a hash algorithm and the HMAC algorithm.
+
+When a symmetric algorithm is used for signing, the signing algorithm is assumed to be an HMAC based
+on the indicated hash algorithm. The HMAC key will either be referenced as part of the usage or will be
+implied by context.
+NOTE 2
+
+The table below is illustrative. It would be modified to reflect the signatures produced by the TPM.
+
+Table 172 — Definition of TPMU_SIGNATURE Union <IN/OUT, S>
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsassa
+
+TPMS_SIGNATURE_RSASSA
+
+TPM_ALG_RSASSA
+
+a PKCS#1v1.5 signature
+
+rsapss
+
+TPMS_SIGNATURE_RSAPSS
+
+TPM_ALG_RSAPSS
+
+a PKCS#1v2.1PSS signature
+
+ecdsa
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_ECDSA
+
+an ECDSA signature
+
+sm2
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_SM2
+
+same format as ECDSA
+
+ecdaa
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_ECDAA
+
+same format as ECDSA
+
+ecschnorr
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_ECSCHNORR
+
+same format as ECDSA
+
+hmac
+
+TPMT_HA
+
+TPM_ALG_HMAC
+
+HMAC signature (required to
+be supported)
+
+any
+
+TPMS_SCHEME_SIGHASH
+
+null
+
+Family “2.0”
+Level 00 Revision 00.99
+
+used to access the hash
+TPM_ALG_NULL
+
+Published
+Copyright © TCG 2006-2013
+
+the NULL signature
+
+Page 123
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.3.5 TPMT_SIGNATURE
+Table 173 shows the basic algorithm-agile structure when a symmetric or asymmetric signature is
+indicated. The sigAlg parameter indicates the algorithm used for the signature. This structure is output
+from the attestation commands and is an input to TPM2_VerifySignature(), TPM2_PolicySigned(), and
+TPM2_FieldUpgradeStart().
+Table 173 — Definition of TPMT_SIGNATURE Structure
+Parameter
+
+Type
+
+Description
+
+sigAlg
+
++TPMI_ALG_SIG_SCHEME
+
+selector of the algorithm used to construct the signature
+
+[sigAlg]signature
+
+TPMU_SIGNATURE
+
+This shall be the actual signature information.
+
+11.4 Key/Secret Exchange
+11.4.1 Introduction
+The structures in this clause are used when a key or secret is being exchanged. The exchange may be in
+
+
+TPM2_StartAuthSession() where the secret is injected for salting the session,
+
+
+
+TPM2_Duplicate(), TPM2_Import, or TPM2_Rewrap() where the secret is the symmetric encryption
+key for the outer wrapper of a duplication blob, or
+
+
+
+TPM2_ActivateIdentity() or TPM2_CreateIdentity() where the secret is the symmetric encryption key
+for the credential blob.
+
+Particulars are described in Part 1.
+11.4.2 TPMU_ENCRYPTED_SECRET
+This structure is used to hold either an ephemeral public point for ECDH, an OAEP-encrypted block for
+RSA, or a symmetrically encrypted value. This structure is defined for the limited purpose of determining
+the size of a TPM2B_ENCRYPTED_SECRET.
+The symmetrically encrypted value may use either CFB or XOR encryption.
+NOTE
+
+Table 174 is illustrative. It would be modified depending on the algorithms supported in the TPM.
+
+Table 174 — Definition of TPMU_ENCRYPTED_SECRET Union <S>
+Parameter
+
+Type
+
+Selector
+
+ecc[sizeof(TPMS_ECC_POINT)]
+
+BYTE
+
+TPM_ALG_ECC
+
+rsa[MAX_RSA_KEY_BYTES]
+
+BYTE
+
+TPM_ALG_RSA
+
+symmetric[sizeof(TPM2B_DIGEST)]
+
+BYTE
+
+TPM_ALG_SYMCIPHER
+
+keyedHash[sizeof(TPM2B_DIGEST)]
+
+BYTE
+
+TPM_ALG_KEYEDHASH
+
+Page 124
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Description
+
+Any symmetrically encrypted
+secret value will be limited to
+be no larger than a digest.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.4.3 TPM2B_ENCRYPTED_SECRET
+Table 175 — Definition of TPM2B_ENCRYPTED_SECRET Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the secret value
+
+secret[size] {:sizeof(TPMU_ENCRYPTED_SECRET)}
+
+BYTE
+
+secret
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 125
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+12 Key/Object Complex
+12.1 Introduction
+An object description requires a TPM2B_PUBLIC structure and may require a TPMT_SENSITIVE
+structure. When the structure is stored off the TPM, the TPMT_SENSITIVE structure is encrypted within a
+TPM2B_PRIVATE structure.
+When the object requires two components for its description, those components are loaded as separate
+parameters in the TPM2_Load() command. When the TPM creates an object that requires both
+components, the TPM will return them as separate parameters from the TPM2_Create() operation.
+The TPM may produce multiple different TPM2B_PRIVATE structures for a single TPM2B_PUBLIC
+structure. Creation of a modified TPM2B_PRIVATE structure requires that the full structure be loaded with
+the TPM2_Load() command, modification of the TPMT_SENSITIVE data, and output of a new
+TPM2B_PRIVATE structure.
+12.2 Public Area Structures
+12.2.1 Description
+This clause defines the TPM2B_PUBLIC structure and the higher-level substructure that may be
+contained in a TPM2B_PUBLIC. The higher-level structures that are currently defined for inclusion in a
+TPM2B_PUBLIC are the
+
+
+structures for asymmetric keys,
+
+
+
+structures for symmetric keys, and
+
+
+
+structures for sealed data.
+
+12.2.2 TPMI_ALG_PUBLIC
+Table 176 — Definition of (TPM_ALG_ID) TPMI_ALG_PUBLIC Type
+Values
+
+Comments
+
+TPM_ALG_KEYEDHASH
+
+required of all TPM
+
+TPM_ALG_SYMCIPHER
+
+required of all TPM
+
+TPM_ALG_RSA
+
+At least one asymmetric algorithm shall be implemented.
+
+TPM_ALG_ECC
+
+At least one asymmetric algorithm shall be implemented.
+
+#TPM_RC_TYPE
+
+response code when a public type is not supported
+
+12.2.3 Type-Specific Parameters
+12.2.3.1
+
+Description
+
+The public area contains two fields (parameters and unique) that vary by object type. The parameters
+field varies according to the type of the object but the contents may be the same across multiple
+instances of a particular type. The unique field format also varies according to the type of the object and
+will also be unique for each instance.
+
+Page 126
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+For a symmetric key (type == TPM_ALG_SYMCIPHER), HMAC key (type == TPM_ALG_KEYEDHASH)
+or data object (also, type == TPM_ALG_KEYEDHASH), the contents of unique shall be computed from
+components of the sensitive area of the object as follows:
+
+unique ≔ HnameAlg(seedValue || sensitive)
+
+(8)
+
+where
+
+HnameAlg()
+
+the hash algorithm used to compute the Name of the object
+
+seedValue
+
+the digest-sized obfuscation value in the sensitive area of a symmetric
+key
+or
+symmetric
+data
+object
+found
+in
+a
+TPMT_SENSITIVE.seedValue.buffer
+
+sensitive
+
+the
+secret
+key/data
+of
+TPMT_SENSITIVE.sensitive.any.buffer
+
+12.2.3.2
+
+the
+
+object
+
+in
+
+the
+
+TPMU_PUBLIC_ID
+Table 177 — Definition of TPMU_PUBLIC_ID Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+keyedHash
+
+TPM2B_DIGEST
+
+TPM_ALG_KEYEDHASH
+
+sym
+
+TPM2B_DIGEST
+
+TPM_ALG_SYMCIPHER
+
+rsa
+
+TPM2B_PUBLIC_KEY_RSA
+
+TPM_ALG_RSA
+
+ecc
+
+TPMS_ECC_POINT
+
+TPM_ALG_ECC
+
+12.2.3.3
+
+Description
+
+TPMS_KEYEDHASH_PARMS
+
+This structure describes the parameters that would appear in the public area of a KEYEDHASH object.
+Note
+
+Although the names are the same, the types of the structures are not the same as for asymmetric
+parameter lists.
+
+Table 178 — Definition of TPMS_KEYEDHASH_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+scheme
+
+TPMT_KEYEDHASH_SCHEME+
+
+Indicates the signing method used for a keyedHash signing
+object. This field also determines the size of the data field for a
+data object created with TPM2_Create(). This field shall not be set
+to TPM_ALG_NULL in a template if either sign or encrypt is SET.
+
+12.2.3.4
+
+TPMS_ASYM_PARMS
+
+This structure contains the common public area parameters for an asymmetric key. The first two
+parameters of the parameter definition structures of an asymmetric key shall have the same two first
+components.
+NOTE
+
+The sign parameter may have a different type in order to allow different schemes to be selected for each
+asymmetric type but the first parameter of each scheme definition shall be a TPM_ALG_ID for a valid
+signing scheme.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 127
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+Table 179 — Definition of TPMS_ASYM_PARMS Structure <>
+
+Parameter
+
+Type
+
+Description
+
+symmetric
+
+TPMT_SYM_DEF_OBJECT+
+
+the companion symmetric algorithm for a restricted
+decryption key and shall be set to a supported symmetric
+algorithm
+This field is optional for keys that are not decryption keys
+and shall be set to TPM_ALG_NULL if not used.
+
+scheme
+
+TPMT_ASYM_SCHEME+
+
+for a key with the sign attribute SET, a valid signing
+scheme for the key type
+for a key with the decrypt attribute SET, a valid key
+exchange protocol
+for a key with sign and decrypt attributes, shall be
+TPM_ALG_NULL
+
+12.2.3.5
+
+TPMS_RSA_PARMS
+
+A TPM compatible with this specification and supporting RSA shall support numPrimes of two and an
+exponent of zero. Support for other values is optional. Use of other exponents in duplicated keys is not
+recommended because the resulting keys would not be interoperable with other TPMs.
+NOTE 1
+
+Implementations are not required to check that exponent is the default exponent. They may fail to load the
+key if exponent is not zero. The reference implementation allows the values listed in the table.
+
+Table 180 — Definition of {RSA} TPMS_RSA_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+symmetric
+
+TPMT_SYM_DEF_OBJECT+ for a restricted decryption key, shall be set to a
+supported symmetric algorithm, key size, and mode.
+if the key is not a restricted decryption key, this field
+shall be set to TPM_ALG_NULL.
+
+scheme
+
+TPMT_RSA_SCHEME+
+
+for a signing key, shall be either TPM_ALG_RSAPSS
+TPM_ALG_RSASSA or TPM_ALG_NULL
+for an unrestricted decryption key, shall be
+TPM_ALG_RSAES,
+TPM_ALG_OAEP,
+or
+TPM_ALG_NULL unless the object also has the sign
+attribute
+for a restricted decryption key, this field shall be
+TPM_ALG_NULL
+NOTE
+
+keyBits
+
+When both sign and decrypt are SET, restricted
+shall be CLEAR and scheme shall be
+TPM_ALG_NULL.
+
+TPMI_RSA_KEY_BITS
+
+number of bits in the public modulus
+
+UINT32
+
+the public exponent
+A prime number greater than 2.
+When zero, indicates that the exponent is the default
+16
+of 2 + 1
+
+#TPM_RC_KEY_SIZE
+exponent
+
+#TPM_RC_VALUE
+
+Page 128
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+12.2.3.6
+
+Part 2: Structures
+
+TPMS_ECC_PARMS
+
+This structure contains the parameters for prime modulus ECC.
+Table 181 — Definition of {ECC} TPMS_ECC_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+symmetric
+
+TPMT_SYM_DEF_OBJECT+
+
+for a restricted decryption key, shall be set to a supported
+symmetric algorithm, key size. and mode.
+if the key is not a restricted decryption key, this field shall be
+set to TPM_ALG_NULL.
+
+scheme
+
+TPMT_ECC_SCHEME+
+
+If the sign attribute of the key is SET, then this shall be a valid
+signing scheme.
+NOTE
+
+If the sign parameter in curveID indicates a mandatory
+scheme, then this field shall have the same value.
+
+If the decrypt attribute of the key is SET, then this shall be a
+valid key exchange scheme or TPM_ALG_NULL.
+If the key is a Storage Key, then this field shall be
+TPM_ALG_NULL.
+curveID
+
+TPMI_ECC_CURVE
+
+ECC curve ID
+
+kdf
+
+TPMT_KDF_SCHEME+
+
+an optional key derivation scheme for generating a symmetric
+key from a Z value
+If the kdf
+parameter associated with curveID is not
+TPM_ALG_NULL then this is required to be NULL.
+NOTE
+
+12.2.3.7
+
+There are currently no commands where this parameter
+has effect and, in the reference code, this field needs to
+be set to TPM_ALG_NULL.
+
+TPMU_PUBLIC_PARMS
+
+Table 182 defines the possible parameter definition structures that may be contained in the public portion
+of a key.
+Table 182 — Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S>
+Parameter
+
+Type
+
+(1)
+
+Selector
+
+Description
+
+keyedHashDetail TPMS_KEYEDHASH_PARMS
+
+TPM_ALG_KEYEDHASH
+
+sign | encrypt | neither
+
+symDetail
+
+TPMS_SYMCIPHER_PARMS
+
+TPM_ALG_SYMCIPHER
+
+a symmetric block cipher
+
+rsaDetail
+
+TPMS_RSA_PARMS
+
+TPM_ALG_RSA
+
+decrypt + sign
+
+(2)
+
+eccDetail
+
+TPMS_ECC_PARMS
+
+TPM_ALG_ECC
+
+decrypt + sign
+
+(2)
+
+asymDetail
+
+TPMS_ASYM_PARMS
+
+common scheme structure
+for RSA and ECC keys
+
+NOTES
+1)
+
+Description column indicates which of TPMA_OBJECT.decrypt or TPMA_OBJECT.sign may be set.
+
+2)
+
+“+” indicates that both may be set but one shall be set. “|” indicates the optional settings.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 129
+October 31, 2013
+
+ Part 2: Structures
+12.2.3.8
+
+Trusted Platform Module Library
+
+TPMT_PUBLIC_PARMS
+
+This structure is used in TPM2_TestParms() to validate that a set of algorithm parameters is supported by
+the TPM.
+Table 183 — Definition of TPMT_PUBLIC_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+type
+
+TPMI_ALG_PUBLIC
+
+the algorithm to be tested
+
+[type]parameters
+
+TPMU_PUBLIC_PARMS the algorithm details
+
+12.2.4 TPMT_PUBLIC
+Table 184 defines the public area structure. The Name of the object is nameAlg concatenated with the
+digest of this structure using nameAlg.
+Table 184 — Definition of TPMT_PUBLIC Structure
+Parameter
+
+Type
+
+Description
+
+type
+
+TPMI_ALG_PUBLIC
+
+“algorithm” associated with this object
+
+nameAlg
+
++TPMI_ALG_HASH
+
+algorithm used for computing the Name of the object
+NOTE
+
+The "+" indicates that the instance of a TPMT_PUBLIC may have
+a "+" to indicate that the nameAlg may be TPM_ALG_NULL.
+
+objectAttributes
+
+TPMA_OBJECT
+
+attributes that, along with type, determine the manipulations of this
+object
+
+authPolicy
+
+TPM2B_DIGEST
+
+optional policy for using this key
+The policy is computed using the nameAlg of the object.
+NOTE
+
+Shall be the Empty Buffer if no authorization policy is present.
+
+[type]parameters
+
+TPMU_PUBLIC_PARMS the algorithm or structure details
+
+[type]unique
+
+TPMU_PUBLIC_ID
+
+Page 130
+October 31, 2013
+
+the unique identifier of the structure
+For an asymmetric key, this would be the public key.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+12.2.5 TPM2B_PUBLIC
+This sized buffer is used to embed a TPMT_PUBLIC in a command.
+Table 185 — Definition of TPM2B_PUBLIC Structure
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of publicArea
+NOTE
+
+publicArea
+
++TPMT_PUBLIC
+
+The “=” will force the TPM to try to unmarshal a
+TPMT_PUBLIC and check that the unmarshaled size
+matches the value of size. If all the required fields of
+a TPMT_PUBLIC are not present, the TPM will return
+an error (generally TPM_RC_SIZE) when attempting
+to unmarshal the TPMT_PUBLIC.
+
+the public area
+NOTE
+
+The “+” indicates that the caller may specify that use
+of TPM_ALG_NULL is allowed for nameAlg.
+
+12.3 Private Area Structures
+12.3.1 Introduction
+The structures in 12.3 define the contents and construction of the private portion of a TPM object. A
+TPM2B_PRIVATE along with a TPM2B_PUBLIC are needed to describe a TPM object.
+A TPM2B_PRIVATE area may be encrypted by different symmetric algorithms or, in some cases, not
+encrypted at all.
+12.3.2 Sensitive Data Structures
+12.3.2.1
+
+Introduction
+
+The structures in 12.3.2 define the presumptive internal representations of the sensitive areas of the
+various entities. A TPM may store the sensitive information in any desired format but when constructing a
+TPM_PRIVATE, the formats in this clause shall be used.
+12.3.2.2
+
+TPM2B_PRIVATE_VENDOR_SPECIFIC
+
+This structure is defined for coding purposes. For IO to the TPM, the sensitive portion of the key will be in
+a canonical form. For an RSA key, this will be one of the prime factors of the public modulus. After
+loading, it is typical that other values will be computed so that computations using the private key will not
+need to start with just one prime factor. This structure allows the vendor-specific structure to use the
+space of the
+The value for RSA_VENDOR_SPECIFIC is determined by the vendor.
+Table 186 — Definition of {RSA} TPM2B_PRIVATE_VENDOR_SPECIFIC Structure<>
+Parameter
+
+Type
+
+size
+
+UINT16
+
+buffer[size]{:PRIVATE_VENDOR_SPECIFIC_BYTES}
+
+BYTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Description
+
+Page 131
+October 31, 2013
+
+ Part 2: Structures
+12.3.2.3
+
+Trusted Platform Module Library
+
+TPMU_SENSITIVE_COMPOSITE
+Table 187 — Definition of TPMU_SENSITIVE_COMPOSITE Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsa
+
+TPM2B_PRIVATE_KEY_RSA
+
+TPM_ALG_RSA
+
+a prime factor of the public
+key
+
+ecc
+
+TPM2B_ECC_PARAMETER
+
+TPM_ALG_ECC
+
+the integer private key
+
+bits
+
+TPM2B_SENSITIVE_DATA
+
+TPM_ALG_KEYEDHASH
+
+the private data
+
+sym
+
+TPM2B_SYM_KEY
+
+TPM_ALG_SYMCIPHER
+
+the symmetric key
+
+any
+
+TPM2B_PRIVATE_VENDOR_SPECIFIC
+
+12.3.2.4
+
+vendor-specific size for key
+storage
+
+TPMT_SENSITIVE
+Table 188 — Definition of TPMT_SENSITIVE Structure
+
+Parameter
+
+Type
+
+Description
+
+sensitiveType
+
+TPMI_ALG_PUBLIC
+
+identifier for the sensitive area
+This shall be the same as the type parameter of the
+associated public area.
+
+authValue
+
+TPM2B_AUTH
+
+user authorization data
+The authValue may be a zero-length string.
+This value shall not be larger than the size of the
+digest produced by the nameAlg of the object.
+
+seedValue
+
+TPM2B_DIGEST
+
+for asymmetric key object, the optional protection
+seed; for other objects, the obfuscation value
+This value shall not be larger than the size of the
+digest produced by nameAlg of the object.
+
+[sensitiveType]sensitive
+
+TPMU_SENSITIVE_COMPOSITE
+
+the type-specific private data
+
+12.3.3 TPM2B_SENSITIVE
+The TPM2B_SENSITIVE structure is used as a parameter in TPM2_LoadExternal(). It is an unencrypted
+sensitive area but it may be encrypted using parameter encryption.
+NOTE
+
+When this structure is unmarshaled, the size of the sensitiveType determines what type of value is
+unmarshaled. Each value of sensitiveType is associated with a TPM2B. It is the maximum size for each of
+the TPM2B values will determine if the unmarshal operation is successful . Since there is no selector for
+the any or vendor options for the union, the maximum input and output sizes for a TMP2B_SENSITIVE
+are not affected by the sizes of those parameters.
+
+Table 189 — Definition of TPM2B_SENSITIVE Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the private structure
+
+sensitiveArea
+
+TPMT_SENSITIVE
+
+an unencrypted sensitive area
+
+Page 132
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+12.3.4 Encryption
+A TPMS_SENSITIVE is the input to the encryption process. All TPMS_ENCRYPT structures are CFBencrypted using a key and Initialization Vector (IV) that are derived from a seed value.
+The method of generating the key and IV is described in “Protected Storage” subclause “Symmetric
+Encryption.” in Part 1.
+12.3.5 Integrity
+The integrity computation is used to ensure that a protected object is modified when stored in memory
+outside of the TPM.
+The method of protecting the integrity of the sensitive area is described in “Protected Storage” subclause
+“Integrity” in Part 1.
+12.3.6 _PRIVATE
+This structure is defined to size the contents of a TPM2B_PRIVATE. This structure is not directly
+marshaled or unmarshaled.
+For TPM2_Duplicate() and TPM2_Import(), the TPM2B_PRIVATE may contain multiply encrypted data
+and two integrity values. In some cases, the sensitive data is not encrypted and the integrity value is not
+present.
+For TPM2_Load() and TPM2_Create(), integrityInner is always present.
+If integrityInner is present, it and sensitive are encrypted as a single block.
+When an integrity value is not needed, it is not present and it is not represented by an Empty Buffer.
+Table 190 — Definition of _PRIVATE Structure <>
+Parameter
+
+Type
+
+Description
+
+integrityOuter
+
+TPM2B_DIGEST
+
+integrityInner
+
+TPM2B_DIGEST
+
+could also be a TPM2B_IV
+
+sensitive
+
+TPMT_SENSITIVE
+
+the sensitive area
+
+12.3.7 TPM2B_PRIVATE
+The TPM2B_PRIVATE structure is used as a parameter in multiple commands that create, load, and
+modify the sensitive area of an object.
+Table 191 — Definition of TPM2B_PRIVATE Structure <IN/OUT, S>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the private structure
+
+buffer[size] {:sizeof(_PRIVATE)}
+
+BYTE
+
+an encrypted private area
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 133
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+12.4 Identity Object
+12.4.1 Description
+An identity object is used to convey credential protection value (CV) to a TPM that can load the object
+associated with the object. The CV is encrypted to a storage key on the target TPM, and if the credential
+integrity checks and the proper object is loaded in the TPM, then the TPM will return the CV.
+12.4.2 _ID_OBJECT
+This structure is used for sizing the TPM2_ID_OBJECT.
+Table 192 — Definition of _ID_OBJECT Structure <>
+Parameter
+
+Type
+
+Description
+
+integrityHMAC
+
+TPM2B_DIGEST
+
+HMAC using the nameAlg of the storage key on the target
+TPM
+
+encIdentity
+
+TPM2B_DIGEST
+
+credential protector information returned if name matches the
+referenced object
+All of the encIdentity is encrypted, including the size field.
+NOTE
+
+The TPM is not required to check that the size is not larger
+than the digest of the nameAlg. However, if the size is
+larger, the ID object may not be usable on a TPM that has
+no digest larger than produced by nameAlg.
+
+12.4.3 TPM2B_ID_OBJECT
+This structure is an output from TPM2_MakeCredential() and is an input to TPM2_ActivateCredential().
+Table 193 — Definition of TPM2B_ID_OBJECT Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the credential structure
+
+credential[size]{:sizeof(_ID_OBJECT)}
+
+BYTE
+
+an encrypted credential area
+
+Page 134
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+13 NV Storage Structures
+13.1 TPM_NV_INDEX
+A TPM_NV_INDEX is used to reference a defined location in NV memory. The format of the Index is
+changed from TPM 1.2 in order to include the Index in the reserved handle space. Handles in this range
+use the digest of the public area of the Index as the Name of the entity in authorization computations
+The 32-bit TPM 1.2 NV Index format is shown in Figure 4. In order to allow the Index to fit into the 24 bits
+available in the reserved handle space, the Index value format is changed as shown in Figure 5.
+3 3 2 2 2 2 2 2 2
+1 0 9 8 7 6 5 4 3
+
+1 1
+6 5
+
+T P U D reserved
+
+0
+0
+
+Purview
+
+Index
+
+Figure 4 — TPM 1.2 TPM_NV_INDEX
+3
+1
+
+2 2
+4 3
+
+0
+0
+
+TPM_HT_NV_INDEX
+
+Index
+
+Figure 5 — TPM 2.0 TPM_NV_INDEX
+NOTE
+
+This TPM_NV_INDEX format does not retain the Purview field and the D bit is not a part of an Index
+handle as in TPM 1.2. The TPMA_NV_PLATFORMCREATE attribute is a property of an Index that
+provides functionality similar to the D bit.
+
+A valid Index handle will have an MSO of TPM_HT_NV_INDEX.
+NOTE
+
+This structure is not used. It is defined here to indicate how the fields of the handle are assigned. The
+exemplary unmarshaling code unmarshals a TPM_HANDLE and validates that it is in the range for a
+TPM_NV_INDEX.
+
+Table 194 — Definition of (UINT32) TPM_NV_INDEX Bits <>
+Bit
+
+Name
+
+Definition
+
+23:0
+
+index
+
+The index of the NV location
+
+31:24
+
+RH_NV
+
+constant value of TPM_HT_NV_INDEX indicating the NV Index range
+
+#TPM_RC_VALUE
+
+response code returned if unmarshaling of this type fails because the handle
+value is incorrect
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 135
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+Table 195 — Options for space Field of TPM_NV_INDEX
+
+Some prior versions of this specification contained a table here that assigned subsets of the index field to
+different entities. Since this assignment was a convention and not an architectural element of the TPM,
+the table was removed and the information is now contained in a registry document that is maintained by
+the TCG.
+13.2 TPMA_NV (NV Index Attributes)
+This structure allows the TPM to keep track of the data and permissions to manipulate an NV Index.
+The platform controls (TPMA_NV_PPWRITE and TPMA_NV_PPREAD) and owner controls
+(TPMA_NV_OWNERWRITE and TPMA_NV_OWNERREAD) give the platform and owner access to NV
+Indexes using platformAuth or ownerAuth rather than the authValue or authPolicy of the Index.
+If access to an NV Index is to be restricted based on PCR, then an appropriate authPolicy shall be
+provided.
+NOTE
+
+platformAuth or ownerAuth can be provided in any type of authorization session or as a password.
+
+If TPMA_NV_AUTHREAD is SET, then the Index may be read if the Index authValue is provided. If
+TPMA_NV_POLICYREAD is SET, then the Index may be read if the Index authPolicy is satisfied.
+At least one of TPMA_NV_PPREAD,
+TPMA_NV_POLICYREAD shall be SET.
+
+TPMA_NV_OWNERREAD,
+
+TPMA_NV_AUTHREAD,
+
+or
+
+If TPMA_NV_AUTHWRITE is SET, then the Index may be written if the Index authValue is provided. If
+TPMA_NV_POLICYWRITE is SET, then the Index may be written if the Index authPolicy is satisfied.
+At least one of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE TPMA_NV_AUTHWRITE, or
+TPMA_NV_POLICYWRITE shall be SET.
+If TPMA_NV_WRITELOCKED is SET, then the Index may not be written. If TPMA_NV_WRITEDEFINE is
+SET, TPMA_NV_WRITELOCKED may not be CLEAR except by deleting and redefining the Index. If
+TPMA_NV_WRITEDEFINE is CLEAR, then TPMA_NV_WRITELOCK will be CLEAR on the next
+TPM2_Startup(TPM_SU_CLEAR).
+If TPMA_NV_READLOCKED is SET, then the Index may not be read. TPMA_NV_READLOCK will be
+CLEAR on the next TPM2_Startup(TPM_SU_CLEAR).
+NOTE
+
+The TPM is expected to maintain indicators to indicate that the Index is temporarily locked. The state of
+these indicators is reported in the TPMA_NV_READLOCKED and TPMA_NV_WRITELOCKED attributes.
+
+If TPMA_NV_EXTEND is SET, then writes to the Index will cause an update of the Index using the extend
+operation with the nameAlg used to create the digest.
+Only one of TPMA_NV_EXTEND, TPMA_NV_COUNTER, or TPMA_NV_BITS may be set.
+When
+the
+Index
+is
+created
+(TPM2_NV_DefineSpace()),
+TPMA_NV_WRITELOCKED,
+TPMA_NV_READLOCKED, TPMA_NV_WRITTEN shall all be CLEAR in the parameter that defines the
+attributes of the created Index.
+
+Page 136
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 196 — Definition of (UINT32) TPMA_NV Bits
+Bit
+
+Name
+
+Description
+
+0
+
+TPMA_NV_PPWRITE
+
+SET (1): The Index data can be written if platformAuth is provided.
+CLEAR (0): Writing of the Index data cannot be authorized with
+platformAuth.
+
+1
+
+TPMA_NV_OWNERWRITE
+
+SET (1): The Index data can be written if ownerAuth is provided.
+CLEAR (0): Writing of the Index data cannot be authorized with
+ownerAuth.
+
+2
+
+TPMA_NV_AUTHWRITE
+
+SET (1): Authorizations to change the Index contents that require
+USER role may be provided with an HMAC session or password.
+CLEAR (0): Authorizations to change the Index contents that require
+USER role may not be provided with an HMAC session or password.
+
+3
+
+TPMA_NV_POLICYWRITE
+
+SET (1): Authorizations to change the Index contents that require
+USER role may be provided with a policy session.
+CLEAR (0): Authorizations to change the Index contents that require
+USER role may not be provided with a policy session.
+NOTE
+
+TPM2_NV_ChangeAuth() always requires that authorization be
+provided in a policy session.
+
+4
+
+TPMA_NV_COUNTER
+
+SET (1): Index contains an 8-octet value that is to be used as a
+counter and can only be modified with TPM2_NV_Increment().
+CLEAR (0): The Index is not a counter.
+
+5
+
+TPMA_NV_BITS
+
+SET (1): Index contains an 8-octet value to be used as a bit field and
+can only be modified with TPM2_NV_SetBits().
+CLEAR (0): The Index is not a bit field.
+
+6
+
+TPMA_NV_EXTEND
+
+SET (1): Index contains a digest-sized value used like a PCR. The
+Index may only be modified using TPM2_NV_Extend. The extend will
+use the nameAlg of the Index.
+CLEAR (0): Index is not a PCR.
+
+9:7
+
+Reserved
+
+shall be zero
+reserved for use in defining additional write controls
+
+10
+
+TPMA_NV_POLICY_DELETE
+
+SET (1): Index may not be deleted unless the authPolicy is satisfied.
+CLEAR (0): Index may be deleted with proper platform or owner
+authorization.
+
+11
+
+TPMA_NV_WRITELOCKED
+
+SET (1): Index cannot be written.
+CLEAR (0): Index can be written.
+
+12
+
+TPMA_NV_WRITEALL
+
+SET (1): A partial write of the Index data is not allowed. The write
+size shall match the defined space size.
+CLEAR (0): Partial writes are allowed. This setting is required if
+TPMA_NV_BITS is SET.
+
+13
+
+TPMA_NV_WRITEDEFINE
+
+SET (1): TPM2_NV_WriteLock() may be used to prevent further
+writes to this location.
+CLEAR (0): TPM2_NV_WriteLock() does not block subsequent
+writes.
+
+14
+
+TPMA_NV_WRITE_STCLEAR
+
+SET (1): TPM2_NV_WriteLock() may be used to prevent further
+writes to this location until the next TPM Reset or TPM Restart.
+CLEAR (0): A write to this Index with a data size of zero does not
+change the write access.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 137
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Bit
+
+Name
+
+Description
+
+15
+
+TPMA_NV_GLOBALLOCK
+
+SET (1): If TPM2_NV_GlobalWriteLock() is successful, then further
+writes to this location are not permitted until the next TPM Reset or
+TPM Restart.
+CLEAR (0): TPM2_NV_GlobalWriteLock() has no effect on the
+writing of the data at this Index.
+
+16
+
+TPMA_NV_PPREAD
+
+SET (1): The Index data can be read if platformAuth is provided.
+CLEAR (0): Reading of the Index data cannot be authorized with
+platformAuth.
+
+17
+
+TPMA_NV_OWNERREAD
+
+SET (1): The Index data can be read if ownerAuth is provided.
+CLEAR (0): Reading of the Index data cannot be authorized with
+ownerAuth.
+
+18
+
+TPMA_NV_AUTHREAD
+
+SET (1): The Index data may be read if the authValue is provided.
+CLEAR (0): Reading of the Index data cannot be authorized with the
+Index authValue.
+
+19
+
+TPMA_NV_POLICYREAD
+
+SET (1): The Index data may be read if the authPolicy is satisfied.
+CLEAR (0): Reading of the Index data cannot be authorized with the
+Index authPolicy.
+
+Reserved
+
+shall be zero
+reserved for use in defining additional read controls
+
+25
+
+TPMA_NV_NO_DA
+
+SET (1): Authorization failures of the Index do not affect the DA logic
+and authorization of the Index is not blocked when the TPM is in
+Lockout mode.
+CLEAR (0): Authorization failures of the Index will increment the
+authorization failure counter and authorizations of this Index are not
+allowed when the TPM is in Lockout mode.
+
+26
+
+TPMA_NV_ORDERLY
+
+SET (1): NV Index state is only required to be saved when the TPM
+performs an orderly shutdown (TPM2_Shutdown()). Only an Index
+with TPMA_NV_COUNTER SET may have this setting.
+CLEAR (0): NV Index state is required to be persistent after the
+command to update the Index completes successfully (that is, the NV
+update is synchronous with the update command).
+
+27
+
+TPMA_NV_CLEAR_STCLEAR
+
+SET (1): TPMA_NV_WRITTEN for the Index is CLEAR by TPM
+Reset or TPM Restart.
+CLEAR (0): TPMA_NV_WRITTEN is not changed by TPM Restart.
+
+24:20
+
+NOTE
+
+This attribute may only be SET if TPMA_NV_COUNTER is not
+SET.
+
+NOTE
+
+If the TPMA_NV_ORDERLY is SET, TPMA_NV_WRITTEN will
+be CLEAR by TPM Reset.
+
+28
+
+TPMA_NV_READLOCKED
+
+SET (1): Reads of the Index are blocked until the next TPM Reset or
+TPM Restart.
+CLEAR (0): Reads of the Index are allowed if proper authorization is
+provided.
+
+29
+
+TPMA_NV_WRITTEN
+
+SET (1): Index has been written.
+CLEAR (0): Index has not been written.
+
+30
+
+TPMA_NV_PLATFORMCREATE
+
+SET (1): This Index may be undefined with platformAuth but not with
+ownerAuth.
+CLEAR (0): This Index may be undefined using ownerAuth but not
+with platformAuth.
+The TPM will validate that this attribute is SET when the Index is
+defined using platformAuth and will validate that this attribute is
+CLEAR when the Index is defined using ownerAuth.
+
+Page 138
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Bit
+
+Name
+
+Description
+
+31
+
+TPMA_NV_READ_STCLEAR
+
+SET (1): TPM2_NV_ReadLock() may be used to SET
+TPMA_NV_READLOCKED for this Index.
+CLEAR (0): TPM2_NV_ReadLock() has no effect on this Index.
+
+13.3 TPMS_NV_PUBLIC
+This structure describes an NV Index.
+Table 197 — Definition of TPMS_NV_PUBLIC Structure
+Name
+
+Type
+
+Description
+
+nvIndex
+
+TPMI_RH_NV_INDEX
+
+the handle of the data area
+
+nameAlg
+
+TPMI_ALG_HASH
+
+hash algorithm used to compute the name of the
+Index and used for the authPolicy
+
+attributes
+
+TPMA_NV
+
+the Index attributes
+
+authPolicy
+
+TPM2B_DIGEST
+
+the access policy for the Index
+
+dataSize{:MAX_NV_INDEX_SIZE}
+
+UINT16
+
+the size of the data area
+The
+maximum
+size is implementationdependent. The minimum maximum size is
+platform-specific.
+
+#TPM_RC_SIZE
+
+response code returned when the requested size
+is too large for the implementation
+
+13.4 TPM2B_NV_PUBLIC
+This structure is used when a TPMS_NV_PUBLIC is sent on the TPM interface.
+Table 198 — Definition of TPM2B_NV_PUBLIC Structure
+Name
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of nvPublic
+
+nvPublic
+
+TPMS_NV_PUBLIC
+
+the public area
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 139
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+14 Context Data
+14.1 Introduction
+This clause defines the contents of the
+TPM2_ContextLoad() command parameters.
+
+TPM2_ContextSave()
+
+response
+
+parameters
+
+and
+
+If the parameters provided by the caller in TPM2_ContextLoad() do not match the values returned by the
+TPM when the context was saved, the integrity check of the TPM2B_CONTEXT will fail and the object or
+session will not be loaded.
+14.2 TPM2B_CONTEXT_SENSITIVE
+This structure holds the object or session context data. When saved, the full structure is encrypted.
+Table 199 — Definition of TPM2B_CONTEXT_SENSITIVE Structure <IN/OUT>
+Parameter
+
+Type
+
+size
+
+Description
+
+UINT16
+
+buffer[size]{:MAX_CONTEXT_SIZE} BYTE
+
+the sensitive data
+
+14.3 TPMS_CONTEXT_DATA
+This structure holds the integrity value and the encrypted data for a context.
+Table 200 — Definition of TPMS_CONTEXT_DATA Structure <IN/OUT, S>
+Parameter
+
+Type
+
+Description
+
+integrity
+
+TPM2B_DIGEST
+
+the integrity value
+
+encrypted
+
+TPM2B_CONTEXT_SENSITIVE
+
+the sensitive area
+
+14.4 TPM2B_CONTEXT_DATA
+This structure is used in a TPMS_CONTEXT.
+Table 201 — Definition of TPM2B_CONTEXT_DATA Structure <IN/OUT>
+Parameter
+
+Type
+
+size
+
+Description
+
+UINT16
+
+buffer[size] {:sizeof(TPMS_CONTEXT_DATA)} BYTE
+
+Page 140
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+14.5 TPMS_CONTEXT
+This structure is used in TPM2_ContextLoad() and TPM2_ContextSave(). If the values of the
+TPMS_CONTEXT structure in TPM2_ContextLoad() are not the same as the values when the context
+was saved (TPM2_ContextSave()), then the TPM shall not load the context.
+Saved object contexts shall not be loaded as long as the associated hierarchy is disabled.
+Saved object contexts are invalidated when the Primary Seed of their hierarchy changes. Objects in the
+Endorsement hierarchy are invalidated when either the EPS or SPS is changed.
+When an object has the stClear attribute, it shall not be possible to reload the context or any descendant
+object after a TPM Reset or TPM Restart.
+NOTE 1
+
+The reference implementation prevents reloads after TPM Restart by including the curre nt value of a
+clearCount in the saved object context. When an object is loaded, this value is compared with the current
+value of the clearCount if the object has the stClear attribute. If the values are not the same, then the
+object cannot be loaded.
+
+A sequence value is contained within the integrity-protected part of the saved context. The sequence
+value is repeated in the sequence parameter of the TPMS_CONTEXT of the context. The sequence
+parameter, along with other values, is used in the generation the protection values of the context.
+If the integrity value of the context is valid, but the sequence value of the decrypted context does not
+match the value in the sequence parameter, then TPM shall enter the failure mode because this is
+indicative of a specific type of attack on the context values.
+NOTE 2
+
+If the integrity value is correct, but the decryption fails and produces the wrong value for sequence, this
+implies that either the TPM is faulty or an external entity is able to forge an integrity val ue for the context
+but they have insufficient information to know what the encryption key of the context. Since the TPM
+generated the valid context, then there is no reason for the sequence value in the context to be decrypted
+incorrectly other than the TPM is faulty or the TPM is under attack. In either case, it is appropriate for the
+TPM to enter failure more.
+
+Table 202 — Definition of TPMS_CONTEXT Structure
+Name
+
+Type
+
+Description
+
+sequence
+
+UINT64
+
+the sequence number of the context
+NOTE
+
+Transient object contexts and
+contexts used different counters.
+
+session
+
+savedHandle
+
+TPMI_DH_CONTEXT
+
+the handle of the session, object or sequence
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy of the context
+
+contextBlob
+
+TPM2B_CONTEXT_DATA
+
+the context data and integrity HMAC
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 141
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+14.6 Parameters of TPMS_CONTEXT
+14.6.1 sequence
+The sequence parameter is used to differentiate the contexts and to allow the TPM to create a different
+encryption key for each context. Objects and sessions use different sequence counters. The sequence
+counter for objects (transient and sequence) is incremented when an object context is saved, and the
+sequence counter for sessions increments when a session is created or when it is loaded
+(TPM2_ContextLoad()). The session sequence number is the contextID counter.
+For a session, the sequence number also allows the TRM to find the “older” contexts so that they may be
+refreshed if the contextID are too widely separated.
+If an input value for sequence is larger than the value used in any saved context, the TPM shall return an
+error (TPM_RC_VALUE) and do no additional processing of the context.
+If the context is a session context and the input value for sequence is less than the current value of
+contextID minus the maximum range for sessions, the TPM shall return an error (TPM_RC_VALUE) and
+do no additional processing of the context.
+14.6.2 savedHandle
+For a session, this is the handle that was assigned to the session when it was saved. For a transient
+object, the handle will have one of the values shown in Table 203.
+If the handle type for savedHandle is TPM_HT_TRANSIENT, then the low order bits are used to
+differentiate static objects from sequence objects.
+If an input value for handle is outside of the range of values used by the TPM, the TPM shall return an
+error (TPM_RC_VALUE) and do no additional processing of the context.
+Table 203 — Context Handle Values
+Value
+
+Description
+
+0x02xxxxxx
+
+an HMAC session context
+
+0x03xxxxxx
+
+a policy session context
+
+0x80000000
+
+an ordinary transient object
+
+0x80000001
+
+a sequence object
+
+0x80000002
+
+a transient object with the stClear attribute SET
+
+Page 142
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+14.6.3 hierarchy
+This is the hierarchy (TPMI_RH_HIERARCHY) for the saved context and determines the proof value used
+in the construction of the encryption and integrity values for the context. For session and sequence
+contexts, the hierarchy is TPM_RC_NULL. The hierarchy for a transient object may be TPM_RH_NULL
+but it is not required.
+14.7 Context Protection
+14.7.1 Context Integrity
+The integrity of the context blob is protected by an HMAC. The integrity value is constructed such that
+changes to the component values will invalidate the context and prevent it from being loaded.
+Previously saved contexts for objects in the Platform hierarchy shall not be loadable after the PPS is
+changed.
+Previously saved contexts for objects in the Storage hierarchy shall not be loadable after the SPS is
+changed.
+Previously saved contexts for objects in the Endorsement hierarchy shall not be loadable after either the
+EPS or SPS is changed.
+Previously saved sessions shall not be loadable after the SPS changes.
+Previously saved contexts for objects that have their stClear attribute SET shall not be loadable after a
+TPM Restart. If a Storage Key has its stClear attribute SET, the descendants of this key shall not be
+loadable after TPM Restart.
+Previously saved contexts for a session and objects shall not be loadable after a TPM Reset.
+A saved context shall not be loaded if its HMAC is not valid. The equation for computing the HMAC for a
+context is found in “Context Integrity Protection” in Part 1.
+14.7.2 Context Confidentiality
+The context data of sessions and objects shall be protected by symmetric encryption using CFB. The
+method for computing the IV and encryption key is found in “Context Confidentiality Protection” in Part 1.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 143
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+15 Creation Data
+15.1 TPMS_CREATION_DATA
+This structure provides information relating to the creation environment for the object. The creation data
+includes the parent Name, parent Qualified Name, and the digest of selected PCR. These values
+represent the environment in which the object was created. Creation data allows a relying party to
+determine if an object was created when some appropriate protections were present.
+When the object is created, the structure shown in Table 204 is generated and a ticket is computed over
+this data.
+If
+the
+parent
+is
+a
+permanent
+handle
+(TPM_RH_OWNER,
+TPM_RH_PLATFORM,
+TPM_RH_ENDORSEMENT, or TPM_RH_NULL), then parentName and parentQualifiedName will be set
+to the parent handle value and parentNameAlg will be TPM_ALG_NULL.
+Table 204 — Definition of TPMS_CREATION_DATA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+pcrSelect
+
+TPML_PCR_SELECTION
+
+list indicating the PCR included in pcrDigest
+
+pcrDigest
+
+TPM2B_DIGEST
+
+digest of the selected PCR using nameAlg of the object for
+which this structure is being created
+pcrDigest.size shall be zero if the pcrSelect list is empty.
+
+locality
+
+TPMA_LOCALITY
+
+the locality at which the object was created
+
+parentNameAlg
+
+TPM_ALG_ID
+
+nameAlg of the parent
+
+parentName
+
+TPM2B_NAME
+
+Name of the parent at time of creation
+The size will match digest size associated with parentNameAlg
+unless it is TPM_ALG_NULL, in which case the size will be 4
+and parentName will be the hierarchy handle.
+
+parentQualifiedName
+
+TPM2B_NAME
+
+Qualified Name of the parent at the time of creation
+Size is the same as parentName.
+
+outsideInfo
+
+TPM2B_DATA
+
+association with additional information added by the key
+creator
+This will be the contents of the outsideInfo parameter in
+TPM2_Create() or TPM2_CreatePrimary().
+
+15.2 TPM2B_CREATION_DATA
+This structure is created by TPM2_Create() and TPM2_CreatePrimary(). It is never entered into the TPM
+and never has a size of zero.
+Table 205 — Definition of TPM2B_CREATION_DATA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of the creation data
+
+creationData
+
+TPMS_CREATION_DATA
+
+Page 144
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Annex A
+(informative)
+Algorithm Constants
+A.1
+
+Introduction
+
+This annex contains constants that are defined by algorithms.
+
+A.2
+A.2.1
+
+Allowed Hash Algorithms
+SHA1
+Table 206 — Defines for SHA1 Hash Values
+
+Name
+
+Value
+
+SHA1_DIGEST_SIZE
+
+20
+
+SHA1_BLOCK_SIZE
+
+64
+
+SHA1_DER_SIZE
+
+Description
+
+15
+
+SHA1_DER
+
+A.2.2
+
+Values are in octets.
+
+{0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,
+0x03,0x02,0x1A,0x05,0x00,0x04,0x14}
+
+SHA256
+Table 207 — Defines for SHA256 Hash Values
+
+Name
+
+Value
+
+SHA256_DIGEST_SIZE
+
+32
+
+SHA256_BLOCK_SIZE
+
+64
+
+SHA256_DER_SIZE
+
+Description
+
+19
+
+SHA256_DER
+
+A.2.3
+
+Values are in octets.
+
+{0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,
+0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
+0x00,0x04,0x20}
+
+SHA384
+Table 208 — Defines for SHA384 Hash Values
+
+Name
+
+Value
+
+SHA384_DIGEST_SIZE
+
+48
+
+SHA384_BLOCK_SIZE
+
+128
+
+SHA384_DER_SIZE
+
+Description
+
+19
+
+SHA384_DER
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Values are in octets.
+
+{0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,
+0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,
+0x00,0x04,0x30}
+
+Published
+Copyright © TCG 2006-2013
+
+Page 145
+October 31, 2013
+
+ Part 2: Structures
+A.2.4
+
+Trusted Platform Module Library
+
+SHA512
+Table 209 — Defines for SHA512 Hash Values
+
+Name
+
+Value
+
+SHA512_DIGEST_SIZE
+
+64
+
+SHA512_BLOCK_SIZE
+
+128
+
+SHA512_DER_SIZE
+
+Description
+
+19
+
+SHA512_DER
+
+A.2.5
+
+Values are in octets.
+
+{0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,
+0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,
+0x00,0x04,0x40}
+
+SM3_256
+Table 210 — Defines for SM3_256 Hash Values
+
+Name
+
+Value
+
+Description
+
+SM3_256_DIGEST_SIZE
+
+32
+
+Values are in octets.
+
+SM3_256_BLOCK_SIZE
+
+64
+
+??
+
+SM3_256_DER_SIZE
+
+18
+
+SM3_256_DER
+
+A.3
+
+{0x30,0x30,0x30,0x0c,0x06,0x08,0x2a,0x81,
+0x1c,0x81,0x45,0x01,0x83,0x11,0x05,0x00,
+0x04,0x20}
+
+Unknown
+
+Architectural Limits
+Table 211 — Defines for Architectural Limits Values
+
+Name
+MAX_SESSION_NUMBER
+
+Page 146
+October 31, 2013
+
+Value
+3
+
+Description
+the maximum number of authorization sessions that may be in a
+command
+This value may be increased if new commands require more than
+two authorization handles.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Annex B
+(informative)
+Implementation Definitions
+B.1
+
+Introduction
+
+This annex contains some of the tables that are used to define the desired implementation for the
+automated tools.
+NOTE
+
+B.2
+
+The reference implementation assumes that stdint.h is used.
+
+Logic Values
+
+The values in this clause are used to see the generation of the subsequent tables. These values should
+not be changed.
+Table 212 — Defines for Logic Values
+Name
+
+Value
+
+YES
+
+1
+
+NO
+
+0
+
+TRUE
+
+1
+
+FALSE
+
+0
+
+SET
+
+1
+
+CLEAR
+
+Description
+
+0
+
+B.3
+
+Processor Values
+
+These values are used to control generation of octet-swapping routines. The canonical octet ordering for
+the TPM input/output buffer is “big endian” with the most significant octet of any datum at the lowest
+address.
+NOTE
+
+The setting for the exemplar is for the x86 family of processor.
+
+Table 213 — Defines for Processor Values
+Name
+
+Value
+
+Description
+
+BIG_ENDIAN_TPM
+
+NO
+
+set to YES or NO according to the processor
+
+LITTLE_ENDIAN_TPM
+
+YES
+
+set to YES or NO according to the processor
+NOTE
+
+NO_AUTO_ALIGN
+
+NO
+
+set to YES if the processor does not allow unaligned accesses
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+BIG_ENDIAN and LITTLE_ENDIAN shall be set to opposite values.
+
+If LITTLE_ENDIAN is YES, then the setting of this value has no effect.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 147
+October 31, 2013
+
+ Part 2: Structures
+
+B.4
+
+Trusted Platform Module Library
+
+Implemented Algorithms
+
+Table 214 is used to indicate the algorithms that are implemented in a TPM. The selections in the Value
+column may be changed to reflect the implementation. The values shown are illustrative.
+The "Implemented" column contains a "Y", "YES", or blank to indicate that the command is present in the
+implementation, an "N" or "NO" to indicate that the command is not implemented.
+The leading and trailing “_” characters are to avoid name space collisions with some crypto libraries.
+
+NOTE
+
+Table 214 — Defines for Implemented Algorithms
+Algorithm Name
+
+Implemented
+
+RSA
+
+YES
+
+SHA1
+
+YES
+
+HMAC
+
+YES
+
+AES
+
+YES
+
+MGF1
+
+YES
+
+XOR
+
+YES
+
+KEYEDHASH
+
+YES
+
+SHA256
+
+YES
+
+SHA384
+
+NO
+
+SHA512
+
+NO
+
+SM3_256
+
+YES
+
+SM4
+
+Comments
+
+YES
+
+REQUIRED, do not change this value
+
+REQUIRED, do not change this value
+
+RSASSA
+
+(YES * RSA)
+
+requires RSA
+
+RSAES
+
+(YES * RSA)
+
+requires RSA
+
+RSAPSS
+
+(YES * RSA)
+
+requires RSA
+
+OAEP
+
+(YES * RSA)
+
+requires RSA
+
+ECC
+
+YES
+
+ECDH
+
+(YES * ECC)
+
+requires ECC
+
+ECDSA
+
+(YES * ECC)
+
+requires ECC
+
+ECDAA
+
+(YES * ECC)
+
+requires ECC
+
+SM2
+
+(YES * ECC)
+
+requires ECC
+
+ECSCHNORR
+
+(YES * ECC)
+
+requires ECC
+
+ECMQV
+
+(NO * ECC)
+
+requires ECC
+
+SYMCIPHER
+KDF1_SP800_56a
+
+YES
+
+REQUIRED, at least one symmetric algorithm shall be implemented
+
+(YES * ECC)
+
+KDF2
+
+NO
+
+KDF1_SP800_108
+
+YES
+
+CTR
+
+YES
+
+OFB
+
+YES
+
+CBC
+
+YES
+
+CFB
+
+YES
+
+ECB
+
+requires ECC
+
+YES
+
+B.5
+
+REQUIRED, do not change this value
+
+Implemented Commands
+
+Page 148
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+This table is used to indicate which of the commands are implemented. In the reference implementation,
+this table determines which commands can be called and drives the generation of various commanddependent switch statements.
+The "Implemented or Dependent" column contains a "Y", "YES", or blank to indicate that the command is
+present in the implementation; an "N" or "NO" to indicate that the command is not implemented; and an
+algorithm value if implementation of the command is dependent on a setting in Table 214. Linkage to
+Table 214 is not required and is provide as a convenience.
+To indicate that the command is implemented, only "Y", "N", blank, or a value from Table 214 is allowed.
+Table 215 — Defines for Implemented Commands
+Name
+ActivateCredential
+
+Implemented
+or Dependent
+
+Comments
+
+YES
+
+Certify
+
+Y
+
+CertifyCreation
+
+Y
+
+ChangeEPS
+
+Y
+
+ChangePPS
+
+Y
+
+Clear
+
+Y
+
+ClearControl
+
+Y
+
+ClockRateAdjust
+
+Y
+
+ClockSet
+
+Y
+
+Commit
+
+ECC
+
+ContextLoad
+
+Y
+
+Context
+
+ContextSave
+
+Y
+
+Context
+
+Create
+
+Y
+
+CreatePrimary
+
+Y
+
+DictionaryAttackLockReset
+
+Y
+
+DictionaryAttackParameters
+
+Y
+
+Duplicate
+
+Y
+
+ECC_Parameters
+
+ECC
+
+ECDH_KeyGen
+
+ECC
+
+ECDH_ZGen
+
+ECC
+
+EncryptDecrypt
+
+Y
+
+EventSequenceComplete
+
+Y
+
+EvictControl
+
+Y
+
+FieldUpgradeData
+
+N
+
+FieldUpgradeStart
+
+N
+
+FirmwareRead
+
+N
+
+FlushContext
+
+Y
+
+GetCapability
+
+Y
+
+GetCommandAuditDigest
+
+Y
+
+GetRandom
+
+Y
+
+GetSessionAuditDigest
+
+Y
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Context
+
+Published
+Copyright © TCG 2006-2013
+
+Page 149
+October 31, 2013
+
+ Part 2: Structures
+
+Name
+
+Trusted Platform Module Library
+Implemented
+or Dependent
+
+Comments
+
+GetTestResult
+
+Y
+
+GetTime
+
+Y
+
+Hash
+
+Y
+
+HashSequenceStart
+
+Y
+
+HierarchyChangeAuth
+
+Y
+
+HierarchyControl
+
+Y
+
+HMAC
+
+Y
+
+HMAC_Start
+
+Y
+
+Import
+
+Y
+
+IncrementalSelfTest
+
+Y
+
+Load
+
+Y
+
+LoadExternal
+
+Y
+
+MakeCredential
+
+Y
+
+NV_Certify
+
+Y
+
+NV_ChangeAuth
+
+Y
+
+NV_DefineSpace
+
+Y
+
+NV_Extend
+
+Y
+
+NV_GlobalWriteLock
+
+Y
+
+NV_Increment
+
+Y
+
+NV_Read
+
+Y
+
+NV_ReadLock
+
+Y
+
+NV_ReadPublic
+
+Y
+
+NV_SetBits
+
+Y
+
+NV_UndefineSpace
+
+Y
+
+NV_UndefineSpaceSpecial
+
+Y
+
+NV_Write
+
+Y
+
+NV_WriteLock
+
+Y
+
+ObjectChangeAuth
+
+Y
+
+PCR_Allocate
+
+Y
+
+PCR_Event
+
+Y
+
+PCR_Extend
+
+Y
+
+PCR_Read
+
+Y
+
+PCR
+
+PCR_Reset
+
+Y
+
+PCR
+
+PCR_SetAuthPolicy
+
+Y
+
+PCR_SetAuthValue
+
+Y
+
+PolicyAuthorize
+
+Y
+
+Policy
+
+PolicyAuthValue
+
+Y
+
+Policy
+
+PolicyCommandCode
+
+Y
+
+Policy
+
+PolicyCounterTimer
+
+Y
+
+Policy
+
+PolicyCpHash
+
+Y
+
+Policy
+
+Page 150
+October 31, 2013
+
+NV
+
+PCR
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+Implemented
+or Dependent
+
+Name
+
+Comments
+
+PolicyDuplicationSelect
+
+Y
+
+Policy
+
+PolicyGetDigest
+
+Y
+
+Policy
+
+PolicyLocality
+
+Y
+
+Policy
+
+PolicyNameHash
+
+Y
+
+Policy
+
+PolicyNV
+
+Y
+
+Policy
+
+PolicyOR
+
+Y
+
+Policy
+
+PolicyPassword
+
+Y
+
+Policy
+
+PolicyPCR
+
+Y
+
+Policy
+
+PolicyPhysicalPresence
+
+Y
+
+Policy
+
+PolicyRestart
+
+Y
+
+PolicySecret
+
+Y
+
+Policy
+
+PolicySigned
+
+Y
+
+Policy
+
+PolicyTicket
+
+Y
+
+Policy
+
+PP_Commands
+
+Y
+
+Quote
+
+Y
+
+ReadClock
+
+Y
+
+ReadPublic
+
+Y
+
+Rewrap
+
+Y
+
+RSA_Decrypt
+
+RSA
+
+RSA_Encrypt
+
+RSA
+
+SelfTest
+
+Y
+
+SequenceComplete
+
+Y
+
+SequenceUpdate
+
+Y
+
+SetAlgorithmSet
+
+Y
+
+SetCommandCodeAuditStatus
+
+Y
+
+SetPrimaryPolicy
+
+Y
+
+Shutdown
+
+Y
+
+Sign
+
+Y
+
+StartAuthSession
+
+Y
+
+Startup
+
+Y
+
+StirRandom
+
+Y
+
+TestParms
+
+Y
+
+Unseal
+
+Y
+
+VerifySignature
+
+Y
+
+ZGen_2Phase
+
+Y
+
+EC_Ephemeral
+
+Y
+
+PolicyNvWritten
+
+Y
+
+B.6
+
+Algorithm Constants
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 151
+October 31, 2013
+
+ Part 2: Structures
+B.6.1
+
+Trusted Platform Module Library
+
+RSA
+Table 216 — Defines for RSA Algorithm Constants
+
+Name
+
+Value
+
+Comments
+
+RSA_KEY_SIZES_BITS
+
+{1024, 2048}
+
+braces because this is a
+list value
+
+MAX_RSA_KEY_BITS
+
+2048
+
+MAX_RSA_KEY_BYTES
+
+((MAX_RSA_KEY_BITS + 7) / 8)
+
+B.6.2
+
+ECC
+Table 217 — Defines for ECC Algorithm Constants
+
+Name
+
+Value
+
+ECC_CURVES
+
+{TPM_ECC_NIST_P256, TPM_ECC_BN_P256,
+TPM_ECC_SM2_P256}
+
+ECC_KEY_SIZES_BITS
+
+{256}
+
+MAX_ECC_KEY_BITS
+
+256
+
+MAX_ECC_KEY_BYTES
+
+((MAX_ECC_KEY_BITS + 7) / 8)
+
+B.6.3
+
+Comments
+
+this is a list value with
+length of one
+
+AES
+Table 218 — Defines for AES Algorithm Constants
+
+Name
+
+Value
+
+AES_KEY_SIZES_BITS
+
+{128}
+
+MAX_AES_KEY_BITS
+
+128
+
+MAX_AES_BLOCK_SIZE_BYTES
+
+16
+
+MAX_AES_KEY_BYTES
+
+((MAX_AES_KEY_BITS + 7) / 8)
+
+B.6.4
+
+Comments
+
+SM4
+Table 219 — Defines for SM4 Algorithm Constants
+
+Name
+
+Value
+
+SM4_KEY_SIZES_BITS
+
+{128}
+
+MAX_SM4_KEY_BITS
+
+128
+
+MAX_SM4_BLOCK_SIZE_BYTES
+
+16
+
+MAX_SM4_KEY_BYTES
+
+((MAX_SM4_KEY_BITS + 7) / 8)
+
+Page 152
+October 31, 2013
+
+Comments
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+B.6.5
+
+Part 2: Structures
+
+Symmetric
+
+The definitions in this table are derived from the implemented symmetric algorithms.
+Table 220 — Defines for Symmetric Algorithm Constants
+Name
+
+Value
+
+MAX_SYM_KEY_BITS
+
+MAX_AES_KEY_BITS
+
+MAX_SYM_KEY_BYTES
+
+MAX_AES_KEY_BYTES
+
+MAX_SYM_BLOCK_SIZE
+
+MAX_AES_BLOCK_SIZE_BYTES
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Comments
+
+Published
+Copyright © TCG 2006-2013
+
+Page 153
+October 31, 2013
+
+ Part 2: Structures
+
+B.7
+
+Trusted Platform Module Library
+
+Implementation Specific Values
+
+The values listed in Table 221 are defined for a specific TPM implementation. The numbers in the Value
+column may be changed to reflect the implementation. The values shown are illustrative.
+Table 221 — Defines for Implementation Values
+Name
+
+Value
+
+Description
+
+FIELD_UPGRADE_IMPLEMENTED
+
+NO
+
+temporary define
+
+BSIZE
+
+UINT16
+
+size used for internal storage of
+the size field of a TPM2B
+This is the definition used for
+the reference design.
+Compilation with this value
+changed may cause warnings
+about conversions.
+
+BUFFER_ALIGNMENT
+
+4
+
+sets the size granularity for the
+buffers in a TPM2B structure
+TPMxB buffers will be assigned
+a space that is a multiple of this
+value. This does not set the size
+limits for IO. Those are set by
+the canonical form of the
+TPMxB
+
+IMPLEMENTATION_PCR
+
+24
+
+the number of PCR in the TPM
+
+PLATFORM_PCR
+
+24
+
+the number of PCR required by
+the relevant platform
+specification
+
+DRTM_PCR
+
+17
+
+the DRTM PCR
+
+HCRTM_PCR
+
+0
+
+the PCR that will receive the HCRTM value at TPM2_Startup
+
+NUM_LOCALITIES
+
+5
+
+the number of localities
+supported by the TPM
+This is expected to be either 5
+for a PC, or 1 for just about
+everything else.
+
+MAX_HANDLE_NUM
+
+3
+
+the maximum number of
+handles in the handle area
+This should be produced by the
+Part 3 parser but is here for
+now.
+
+MAX_ACTIVE_SESSIONS
+
+64
+
+the number of simultaneously
+active sessions that are
+supported by the TPM
+implementation
+
+CONTEXT_SLOT
+
+UINT16
+
+the type of an entry in the array
+of saved contexts
+
+CONTEXT_COUNTER
+
+UINT64
+
+the type of the saved session
+counter
+
+MAX_LOADED_SESSIONS
+
+3
+
+the number of sessions that the
+TPM may have in memory
+
+MAX_SESSION_NUM
+
+3
+
+this is the current maximum
+value
+
+Page 154
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Name
+
+Value
+
+Description
+
+MAX_LOADED_OBJECTS
+
+3
+
+the number of simultaneously
+loaded objects that are
+supported by the TPM; this
+number does not include the
+objects that may be placed in
+NV memory by
+TPM2_EvictControl().
+
+MIN_EVICT_OBJECTS
+
+2
+
+the minimum number of evict
+objects supported by the TPM
+
+PCR_SELECT_MIN
+
+((PLATFORM_PCR+7)/8)
+
+PCR_SELECT_MAX
+
+((IMPLEMENTATION_PCR+7)/8)
+
+NUM_POLICY_PCR_GROUP
+
+1
+
+number of PCR groups that
+have individual policies
+
+NUM_AUTHVALUE_PCR_GROUP
+
+1
+
+number of PCR groups that
+have individual authorization
+values
+
+MAX_CONTEXT_SIZE
+
+4000
+
+This may be larger than
+necessary
+
+MAX_DIGEST_BUFFER
+
+1024
+
+MAX_NV_INDEX_SIZE
+
+2048
+
+maximum data size allowed in
+an NV Index
+
+MAX_NV_BUFFER_SIZE
+
+1024
+
+maximum data size in one NV
+read or write command
+
+MAX_CAP_BUFFER
+
+1024
+
+NV_MEMORY_SIZE
+
+16384
+
+NUM_STATIC_PCR
+
+16
+
+MAX_ALG_LIST_SIZE
+
+64
+
+number of algorithms that can
+be in a list
+
+TIMER_PRESCALE
+
+100000
+
+nominal value for the pre-scale
+value of Clock (the number of
+cycles of the TPM's oscillator for
+each increment of Clock)
+
+PRIMARY_SEED_SIZE
+
+32
+
+size of the Primary Seed in
+octets
+
+CONTEXT_ENCRYPT_ALG
+
+TPM_ALG_AES
+
+context encryption algorithm
+
+CONTEXT_ENCRYPT_KEY_BITS
+
+MAX_SYM_KEY_BITS
+
+context encryption key size in
+bits
+
+CONTEXT_ENCRYPT_KEY_BYTES
+
+((CONTEXT_ENCRYPT_KEY_BITS+7
+)/8)
+
+CONTEXT_INTEGRITY_HASH_ALG
+
+TPM_ALG_SHA256
+
+context integrity hash algorithm
+
+CONTEXT_INTEGRITY_HASH_SIZE
+
+SHA256_DIGEST_SIZE
+
+number of byes in the context
+integrity digest
+
+PROOF_SIZE
+
+CONTEXT_INTEGRITY_HASH_SIZE
+
+size of proof value in octets
+This size of the proof should be
+consistent with the digest size
+used for context integrity.
+
+NV_CLOCK_UPDATE_INTERVAL
+
+12
+
+the update interval expressed
+as a power of 2 seconds
+
+size of NV memory in octets
+
+A value of 12 is 4,096 seconds
+(~68 minutes).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 155
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Name
+
+Value
+
+Description
+
+NUM_POLICY_PCR
+
+1
+
+number of PCR that allow
+policy/auth
+
+MAX_COMMAND_SIZE
+
+4096
+
+maximum size of a command
+
+MAX_RESPONSE_SIZE
+
+4096
+
+maximum size of a response
+
+ORDERLY_BITS
+
+8
+
+number between 1 and 32
+inclusive
+
+MAX_ORDERLY_COUNT
+
+((1 << ORDERLY_BITS) - 1)
+
+maximum count of orderly
+counter before NV is updated
+This must be of the form 2N – 1
+where 1 ≤ N ≤ 32.
+
+ALG_ID_FIRST
+
+TPM_ALG_FIRST
+
+used by GetCapability()
+processing to bound the
+algorithm search
+
+ALG_ID_LAST
+
+TPM_ALG_LAST
+
+used by GetCapability()
+processing to bound the
+algorithm search
+
+MAX_SYM_DATA
+
+128
+
+this is the maximum number of
+octets that may be in a sealed
+blob.
+
+MAX_RNG_ENTROPY_SIZE
+
+64
+
+RAM_INDEX_SPACE
+
+512
+
+RSA_DEFAULT_PUBLIC_EXPONENT
+
+0x00010001
+
+216 + 1
+
+ENABLE_PCR_NO_INCREMENT
+
+YES
+
+indicates if the
+TPM_PT_PCR_NO_INCREME
+NT group is implemented
+
+CRT_FORMAT_RSA
+
+YES
+
+PRIVATE_VENDOR_SPECIFIC_BYTES
+
+((MAX_RSA_KEY_BYTES/2) * (3 +
+CRT_FORMAT_RSA * 2))
+
+Page 156
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+
diff --git a/trunks/generator/raw_structures_fixed.txt b/trunks/generator/raw_structures_fixed.txt
new file mode 100644
index 0000000..4abeff4
--- /dev/null
+++ b/trunks/generator/raw_structures_fixed.txt
@@ -0,0 +1,17774 @@
+Trusted Platform Module Library
+Part 2: Structures
+Family “2.0”
+Level 00 Revision 00.99
+October 31, 2013
+
+Contact: admin@trustedcomputinggroup.org
+
+Published
+Copyright © TCG 2006-2013
+
+TCG
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Licenses and Notices
+1. Copyright Licenses:
+
+
+Trusted Computing Group (TCG) grants to the user of the source code in this specification (the
+“Source Code”) a worldwide, irrevocable, nonexclusive, royalty free, copyright license to
+reproduce, create derivative works, distribute, display and perform the Source Code and
+derivative works thereof, and to grant others the rights granted herein.
+
+
+
+The TCG grants to the user of the other parts of the specification (other than the Source Code)
+the rights to reproduce, distribute, display, and perform the specification solely for the purpose of
+developing products based on such documents.
+
+2. Source Code Distribution Conditions:
+
+
+Redistributions of Source Code must retain the above copyright licenses, this list of conditions
+and the following disclaimers.
+
+
+
+Redistributions in binary form must reproduce the above copyright licenses, this list of conditions
+and the following disclaimers in the documentation and/or other materials provided with the
+distribution.
+
+3. Disclaimers:
+
+
+THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF
+LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH
+RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)
+THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.
+Contact TCG Administration (admin@trustedcomputinggroup.org) for information on specification
+licensing rights available through TCG membership agreements.
+
+
+
+THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES
+WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF
+INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF
+ANY PROPOSAL, SPECIFICATION OR SAMPLE.
+
+
+
+Without limitation, TCG and its members and licensors disclaim all liability, including liability for
+infringement of any proprietary rights, relating to use of information in this specification and to the
+implementation of this specification, and TCG disclaims all liability for cost of procurement of
+substitute goods or services, lost profits, loss of use, loss of data or any incidental, consequential,
+direct, indirect, or special damages, whether under contract, tort, warranty or otherwise, arising in
+any way out of use or reliance upon this specification or any information herein.
+
+Any marks and brands contained herein are the property of their respective owners.
+
+Page ii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+CONTENTS
+1
+
+Scope .................................................................................................................................................... 1
+
+2
+
+Terms and definitions ............................................................................................................................ 1
+
+3
+
+Symbols and abbreviated terms ............................................................................................................ 1
+
+4
+
+Notation ................................................................................................................................................. 1
+4.1
+Introduction ................................................................................................................................ 1
+4.2
+Named Constants ...................................................................................................................... 2
+4.3
+Data Type Aliases (typedefs) .................................................................................................... 3
+4.4
+Enumerations............................................................................................................................. 3
+4.5
+Interface Type ............................................................................................................................ 4
+4.6
+Arrays ........................................................................................................................................ 5
+4.7
+Structure Definitions .................................................................................................................. 6
+4.8
+Conditional Types ...................................................................................................................... 7
+4.9
+Unions........................................................................................................................................ 8
+4.9.1
+Introduction...................................................................................................................... 8
+4.9.2
+Union Definition ............................................................................................................... 8
+4.9.3
+Union Instance ................................................................................................................ 9
+4.9.4
+Union Selector Definition ............................................................................................... 10
+4.10 Bit Field Definitions .................................................................................................................. 11
+4.11 Parameter Limits ..................................................................................................................... 11
+4.12 Enumeration Macro ................................................................................................................. 13
+4.13 Size Checking .......................................................................................................................... 13
+4.14 Data Direction .......................................................................................................................... 14
+4.15 Structure Validations ............................................................................................................... 14
+4.16 Name Prefix Convention .......................................................................................................... 14
+4.17 Data Alignment ........................................................................................................................ 15
+4.18 Parameter Unmarshaling Errors .............................................................................................. 15
+
+5
+
+Base Types ......................................................................................................................................... 17
+5.1
+Primitive Types ........................................................................................................................ 17
+5.2
+Miscellaneous Types ............................................................................................................... 17
+
+6
+
+Constants ............................................................................................................................................ 18
+6.1
+TPM_SPEC (Specification Version Values) ............................................................................ 18
+6.2
+TPM_GENERATED ................................................................................................................. 18
+6.3
+TPM_ALG_ID .......................................................................................................................... 19
+6.4
+TPM_ECC_CURVE ................................................................................................................. 22
+6.5
+TPM_CC (Command Codes) .................................................................................................. 22
+6.5.1
+Format ........................................................................................................................... 22
+6.5.2
+Description .................................................................................................................... 23
+6.5.3
+TPM_CC Listing ............................................................................................................ 24
+6.6
+TPM_RC (Response Codes) ................................................................................................... 28
+6.6.1
+Description .................................................................................................................... 28
+6.6.2
+Response Code Formats .............................................................................................. 29
+6.6.3
+TPM_RC Values ........................................................................................................... 32
+6.7
+TPM_CLOCK_ADJUST ........................................................................................................... 37
+6.8
+TPM_EO (EA Arithmetic Operands) ........................................................................................ 37
+6.9
+TPM_ST (Structure Tags) ....................................................................................................... 38
+6.10 TPM_SU (Startup Type) .......................................................................................................... 40
+6.11 TPM_SE (Session Type) ......................................................................................................... 40
+6.12 TPM_CAP (Capabilities) .......................................................................................................... 41
+6.13 TPM_PT (Property Tag) .......................................................................................................... 41
+6.14 TPM_PT_PCR (PCR Property Tag) ........................................................................................ 47
+6.15 TPM_PS (Platform Specific) .................................................................................................... 49
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page iii
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+7
+
+Handles ............................................................................................................................................... 50
+7.1
+Introduction .............................................................................................................................. 50
+7.2
+TPM_HT (Handle Types) ......................................................................................................... 50
+7.3
+Persistent Handle Sub-ranges................................................................................................. 51
+7.4
+TPM_RH (Permanent Handles)............................................................................................... 52
+7.5
+TPM_HC (Handle Value Constants) ....................................................................................... 53
+
+8
+
+Attribute Structures .............................................................................................................................. 55
+8.1
+Description ............................................................................................................................... 55
+8.2
+TPMA_ALGORITHM ............................................................................................................... 55
+8.3
+TPMA_OBJECT (Object Attributes) ........................................................................................ 55
+8.3.1
+Introduction.................................................................................................................... 55
+8.3.2
+Structure Definition ........................................................................................................ 56
+8.3.3
+Attribute Descriptions .................................................................................................... 57
+8.3.3.1
+Introduction ............................................................................................................ 57
+8.3.3.2
+Bit[1] – fixedTPM ................................................................................................... 57
+8.3.3.3
+Bit[2] – stClear ....................................................................................................... 58
+8.3.3.4
+Bit[4] – fixedParent ................................................................................................ 58
+8.3.3.5
+Bit[5] – sensitiveDataOrigin ................................................................................... 58
+8.3.3.6
+Bit[6] – userWithAuth............................................................................................. 59
+8.3.3.7
+Bit[7] – adminWithPolicy........................................................................................ 59
+8.3.3.8
+Bit[10] – noDA ....................................................................................................... 59
+8.3.3.9
+Bit[11] – encryptedDuplication .............................................................................. 60
+8.3.3.10
+Bit[16] – restricted ................................................................................................. 60
+8.3.3.11
+Bit[17] – decrypt .................................................................................................... 61
+8.3.3.12
+Bit[18] – sign .......................................................................................................... 61
+8.4
+TPMA_SESSION (Session Attributes) .................................................................................... 62
+8.5
+TPMA_LOCALITY (Locality Attribute) ..................................................................................... 63
+8.6
+TPMA_PERMANENT .............................................................................................................. 64
+8.7
+TPMA_STARTUP_CLEAR ...................................................................................................... 65
+8.8
+TPMA_MEMORY .................................................................................................................... 66
+8.9
+TPMA_CC (Command Code Attributes) ................................................................................. 67
+8.9.1
+Introduction.................................................................................................................... 67
+8.9.2
+Structure Definition ........................................................................................................ 67
+8.9.3
+Field Descriptions .......................................................................................................... 67
+8.9.3.1
+Bits[15:0] – commandIndex ................................................................................... 67
+8.9.3.2
+Bit[22] – nv ............................................................................................................ 67
+8.9.3.3
+Bit[23] – extensive ................................................................................................. 67
+8.9.3.4
+Bit[24] – flushed ..................................................................................................... 68
+8.9.3.5
+Bits[27:25] – cHandles .......................................................................................... 68
+8.9.3.6
+Bit[28] – rHandle .................................................................................................... 68
+8.9.3.7
+Bit[29] – V .............................................................................................................. 69
+8.9.3.8
+Bits[31:30] – Res ................................................................................................... 69
+
+9
+
+Interface Types .................................................................................................................................... 70
+9.1
+Introduction .............................................................................................................................. 70
+9.2
+TPMI_YES_NO ....................................................................................................................... 70
+9.3
+TPMI_DH_OBJECT ................................................................................................................. 70
+9.4
+TPMI_DH_PERSISTENT ........................................................................................................ 71
+9.5
+TPMI_DH_ENTITY .................................................................................................................. 71
+9.6
+TPMI_DH_PCR ....................................................................................................................... 72
+9.7
+TPMI_SH_AUTH_SESSION ................................................................................................... 72
+9.8
+TPMI_SH_HMAC .................................................................................................................... 72
+9.9
+TPMI_SH_POLICY .................................................................................................................. 72
+9.10 TPMI_DH_CONTEXT .............................................................................................................. 73
+9.11 TPMI_RH_HIERARCHY .......................................................................................................... 73
+9.12 TPMI_RH_ENABLES .............................................................................................................. 73
+
+Page iv
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+9.13
+9.14
+9.15
+9.16
+9.17
+9.18
+9.19
+9.20
+9.21
+9.22
+9.23
+9.24
+9.25
+9.26
+9.27
+9.28
+9.29
+9.30
+10
+
+Part 2: Structures
+
+TPMI_RH_HIERARCHY_AUTH .............................................................................................. 74
+TPMI_RH_PLATFORM ........................................................................................................... 74
+TPMI_RH_OWNER ................................................................................................................. 74
+TPMI_RH_ENDORSEMENT ................................................................................................... 75
+TPMI_RH_PROVISION ........................................................................................................... 75
+TPMI_RH_CLEAR ................................................................................................................... 75
+TPMI_RH_NV_AUTH .............................................................................................................. 76
+TPMI_RH_LOCKOUT ............................................................................................................. 76
+TPMI_RH_NV_INDEX ............................................................................................................. 76
+TPMI_ALG_HASH ................................................................................................................... 77
+TPMI_ALG_ASYM (Asymmetric Algorithms) .......................................................................... 77
+TPMI_ALG_SYM (Symmetric Algorithms) .............................................................................. 78
+TPMI_ALG_SYM_OBJECT ..................................................................................................... 78
+TPMI_ALG_SYM_MODE ........................................................................................................ 79
+TPMI_ALG_KDF (Key and Mask Generation Functions) ........................................................ 79
+TPMI_ALG_SIG_SCHEME ..................................................................................................... 80
+TPMI_ECC_KEY_EXCHANGE ............................................................................................... 80
+TPMI_ST_COMMAND_TAG ................................................................................................... 80
+
+Structure Definitions ............................................................................................................................ 81
+10.1 TPMS_ALGORITHM_DESCRIPTION .................................................................................... 81
+10.2 Hash/Digest Structures ............................................................................................................ 81
+10.2.1
+TPMU_HA (Hash) ......................................................................................................... 81
+10.2.2
+TPMT_HA...................................................................................................................... 82
+10.3 Sized Buffers ........................................................................................................................... 82
+10.3.1
+Introduction.................................................................................................................... 82
+10.3.2
+TPM2B_DIGEST ........................................................................................................... 83
+10.3.3
+TPM2B_DATA ............................................................................................................... 83
+10.3.4
+TPM2B_NONCE ........................................................................................................... 83
+10.3.5
+TPM2B_AUTH .............................................................................................................. 83
+10.3.6
+TPM2B_OPERAND ...................................................................................................... 84
+10.3.7
+TPM2B_EVENT ............................................................................................................ 84
+10.3.8
+TPM2B_MAX_BUFFER ................................................................................................ 84
+10.3.9
+TPM2B_MAX_NV_BUFFER ......................................................................................... 84
+10.3.10 TPM2B_TIMEOUT ........................................................................................................ 85
+10.3.11 TPM2B_IV ..................................................................................................................... 85
+10.4 Names ..................................................................................................................................... 85
+10.4.1
+Introduction.................................................................................................................... 85
+10.4.2
+TPMU_NAME ................................................................................................................ 85
+10.4.3
+TPM2B_NAME .............................................................................................................. 86
+10.5 PCR Structures ........................................................................................................................ 86
+10.5.1
+TPMS_PCR_SELECT ................................................................................................... 86
+10.5.2
+TPMS_PCR_SELECTION ............................................................................................ 87
+10.6 Tickets ..................................................................................................................................... 87
+10.6.1
+Introduction.................................................................................................................... 87
+10.6.2
+A NULL Ticket ............................................................................................................... 88
+10.6.3
+TPMT_TK_CREATION ................................................................................................. 89
+10.6.4
+TPMT_TK_VERIFIED ................................................................................................... 90
+10.6.5
+TPMT_TK_AUTH .......................................................................................................... 91
+10.6.6
+TPMT_TK_HASHCHECK ............................................................................................. 92
+10.7 Property Structures .................................................................................................................. 92
+10.7.1
+TPMS_ALG_PROPERTY ............................................................................................. 92
+10.7.2
+TPMS_TAGGED_PROPERTY ..................................................................................... 92
+10.7.3
+TPMS_TAGGED_PCR_SELECT ................................................................................. 93
+10.8 Lists ......................................................................................................................................... 93
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page v
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.8.1
+TPML_CC...................................................................................................................... 93
+10.8.2
+TPML_CCA ................................................................................................................... 94
+10.8.3
+TPML_ALG.................................................................................................................... 94
+10.8.4
+TPML_HANDLE ............................................................................................................ 94
+10.8.5
+TPML_DIGEST ............................................................................................................. 95
+10.8.6
+TPML_DIGEST_VALUES ............................................................................................. 95
+10.8.7
+TPM2B_DIGEST_VALUES........................................................................................... 95
+10.8.8
+TPML_PCR_SELECTION............................................................................................. 96
+10.8.9
+TPML_ALG_PROPERTY.............................................................................................. 96
+10.8.10 TPML_TAGGED_TPM_PROPERTY ............................................................................ 96
+10.8.11 TPML_TAGGED_PCR_PROPERTY ............................................................................ 97
+10.8.12 TPML_ECC_CURVE .................................................................................................... 97
+10.9 Capabilities Structures ............................................................................................................. 97
+10.9.1
+TPMU_CAPABILITIES .................................................................................................. 97
+10.9.2
+TPMS_CAPABILITY_DATA .......................................................................................... 98
+10.10 Clock/Counter Structures ........................................................................................................ 98
+10.10.1 TPMS_CLOCK_INFO ................................................................................................... 98
+10.10.2 Clock ............................................................................................................................. 98
+10.10.3 ResetCount ................................................................................................................... 98
+10.10.4 RestartCount ................................................................................................................. 99
+10.10.5 Safe ............................................................................................................................... 99
+10.10.6 TPMS_TIME_INFO ....................................................................................................... 99
+10.11 TPM Attestation Structures .................................................................................................... 100
+10.11.1 Introduction.................................................................................................................. 100
+10.11.2 TPMS_TIME_ATTEST_INFO ..................................................................................... 100
+10.11.3 TPMS_CERTIFY_INFO .............................................................................................. 100
+10.11.1 TPMS_QUOTE_INFO ................................................................................................. 100
+10.11.2 TPMS_COMMAND_AUDIT_INFO .............................................................................. 101
+10.11.3 TPMS_SESSION_AUDIT_INFO ................................................................................. 101
+10.11.4 TPMS_CREATION_INFO ........................................................................................... 101
+10.11.5 TPMS_NV_CERTIFY_INFO ....................................................................................... 101
+10.11.6 TPMI_ST_ATTEST ..................................................................................................... 102
+10.11.7 TPMU_ATTEST .......................................................................................................... 102
+10.11.8 TPMS_ATTEST .......................................................................................................... 103
+10.11.9 TPM2B_ATTEST ........................................................................................................ 103
+10.12 Authorization Structures ........................................................................................................ 104
+10.12.1 TPMS_AUTH_COMMAND ......................................................................................... 104
+10.12.2 TPMS_AUTH_RESPONSE ........................................................................................ 104
+11
+
+Algorithm Parameters and Structures ............................................................................................... 105
+11.1 Symmetric .............................................................................................................................. 105
+11.1.1
+Introduction.................................................................................................................. 105
+11.1.2
+TPMI_AES_KEY_BITS ............................................................................................... 105
+11.1.3
+TPMI_SM4_KEY_BITS ............................................................................................... 105
+11.1.4
+TPMU_SYM_KEY_BITS ............................................................................................. 106
+11.1.5
+TPMU_SYM_MODE ................................................................................................... 106
+11.1.6
+TPMU_SYM_DETAILS ............................................................................................... 107
+11.1.7
+TPMT_SYM_DEF ....................................................................................................... 107
+11.1.8
+TPMT_SYM_DEF_OBJECT ....................................................................................... 107
+11.1.9
+TPM2B_SYM_KEY ..................................................................................................... 108
+11.1.10 TPMS_SYMCIPHER_PARMS .................................................................................... 108
+11.1.11 TPM2B_SENSITIVE_DATA ........................................................................................ 108
+11.1.12 TPMS_SENSITIVE_CREATE ..................................................................................... 109
+11.1.13 TPM2B_SENSITIVE_CREATE ................................................................................... 110
+11.1.14 TPMS_SCHEME_SIGHASH....................................................................................... 110
+11.1.15 TPMI_ALG_HASH_SCHEME ..................................................................................... 110
+
+Page vi
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.16 HMAC_SIG_SCHEME ................................................................................................ 110
+11.1.17 TPMS_SCHEME_XOR ............................................................................................... 111
+11.1.18 TPMU_SCHEME_HMAC ............................................................................................ 111
+11.1.19 TPMT_KEYEDHASH_SCHEME ................................................................................. 111
+11.2 Asymmetric ............................................................................................................................ 112
+11.2.1
+Signing Schemes ........................................................................................................ 112
+11.2.1.1
+Introduction .......................................................................................................... 112
+11.2.1.2
+RSA_SIG_SCHEMES ......................................................................................... 112
+11.2.1.3
+ECC_SIG_SCHEMES ......................................................................................... 112
+11.2.1.4
+TPMS_SCHEME_ECDAA................................................................................... 112
+11.2.1.5
+TPMU_SIG_SCHEME......................................................................................... 113
+11.2.1.6
+TPMT_SIG_SCHEME ......................................................................................... 113
+11.2.2
+Encryption Schemes ................................................................................................... 114
+11.2.2.1
+Introduction .......................................................................................................... 114
+11.2.2.2
+TPMS_SCHEME_OAEP ..................................................................................... 114
+11.2.2.3
+TPMS_SCHEME_ECDH ..................................................................................... 114
+11.2.3
+Key Derivation Schemes ............................................................................................. 114
+11.2.3.1
+Introduction .......................................................................................................... 114
+11.2.3.2
+TPMS_SCHEME_MGF1 ..................................................................................... 114
+11.2.3.3
+TPMS_SCHEME_KDF1_SP800_56a ................................................................. 114
+11.2.3.4
+TPMS_SCHEME_KDF2 ...................................................................................... 115
+11.2.3.5
+TPMS_SCHEME_KDF1_SP800_108 ................................................................. 115
+11.2.3.6
+TPMU_KDF_SCHEME........................................................................................ 115
+11.2.3.7
+TPMT_KDF_SCHEME ........................................................................................ 115
+11.2.3.8
+TPMI_ALG_ASYM_SCHEME ............................................................................. 116
+11.2.3.9
+TPMU_ASYM_SCHEME..................................................................................... 116
+11.2.3.10 TPMT_ASYM_SCHEME ..................................................................................... 117
+11.2.4
+RSA ............................................................................................................................. 117
+11.2.4.1
+TPMI_ALG_RSA_SCHEME ................................................................................ 117
+11.2.4.2
+TPMT_RSA_SCHEME ........................................................................................ 117
+11.2.4.3
+TPMI_ALG_RSA_DECRYPT .............................................................................. 118
+11.2.4.4
+TPMT_RSA_DECRYPT ...................................................................................... 118
+11.2.4.5
+TPM2B_PUBLIC_KEY_RSA ............................................................................... 118
+11.2.4.6
+TPMI_RSA_KEY_BITS ....................................................................................... 118
+11.2.4.7
+TPM2B_PRIVATE_KEY_RSA ............................................................................ 119
+11.2.5
+ECC ............................................................................................................................. 120
+11.2.5.1
+TPM2B_ECC_PARAMETER .............................................................................. 120
+11.2.5.2
+TPMS_ECC_POINT ............................................................................................ 120
+11.2.5.3
+TPM2B_ECC_POINT .......................................................................................... 120
+11.2.5.4
+TPMI_ALG_ECC_SCHEME ............................................................................... 121
+11.2.5.5
+TPMI_ECC_CURVE ............................................................................................ 121
+11.2.5.6
+TPMT_ECC_SCHEME........................................................................................ 121
+11.2.5.7
+TPMS_ALGORITHM_DETAIL_ECC ................................................................... 122
+11.3 Signatures.............................................................................................................................. 122
+11.3.1
+TPMS_SIGNATURE_RSASSA .................................................................................. 122
+11.3.2
+TPMS_SIGNATURE_RSAPSS .................................................................................. 122
+11.3.3
+TPMS_SIGNATURE_ECDSA ..................................................................................... 123
+11.3.4
+TPMU_SIGNATURE ................................................................................................... 123
+11.3.5
+TPMT_SIGNATURE ................................................................................................... 124
+11.4 Key/Secret Exchange ............................................................................................................ 124
+11.4.1
+Introduction.................................................................................................................. 124
+11.4.2
+TPMU_ENCRYPTED_SECRET ................................................................................. 124
+11.4.3
+TPM2B_ENCRYPTED_SECRET ............................................................................... 125
+12
+
+Key/Object Complex.......................................................................................................................... 126
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page vii
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+12.1 Introduction ............................................................................................................................ 126
+12.2 Public Area Structures ........................................................................................................... 126
+12.2.1
+Description .................................................................................................................. 126
+12.2.2
+TPMI_ALG_PUBLIC ................................................................................................... 126
+12.2.3
+Type-Specific Parameters ........................................................................................... 126
+12.2.3.1
+Description .......................................................................................................... 126
+12.2.3.2
+TPMU_PUBLIC_ID .............................................................................................. 127
+12.2.3.3
+TPMS_KEYEDHASH_PARMS ........................................................................... 127
+12.2.3.4
+TPMS_ASYM_PARMS ....................................................................................... 127
+12.2.3.5
+TPMS_RSA_PARMS .......................................................................................... 128
+12.2.3.6
+TPMS_ECC_PARMS .......................................................................................... 129
+12.2.3.7
+TPMU_PUBLIC_PARMS .................................................................................... 129
+12.2.3.8
+TPMT_PUBLIC_PARMS ..................................................................................... 130
+12.2.4
+TPMT_PUBLIC ........................................................................................................... 130
+12.2.5
+TPM2B_PUBLIC ......................................................................................................... 131
+12.3 Private Area Structures ......................................................................................................... 131
+12.3.1
+Introduction.................................................................................................................. 131
+12.3.2
+Sensitive Data Structures ............................................................................................ 131
+12.3.2.1
+Introduction .......................................................................................................... 131
+12.3.2.2
+TPM2B_PRIVATE_VENDOR_SPECIFIC ........................................................... 131
+12.3.2.3
+TPMU_SENSITIVE_COMPOSITE ...................................................................... 132
+12.3.2.4
+TPMT_SENSITIVE .............................................................................................. 132
+12.3.3
+TPM2B_SENSITIVE ................................................................................................... 132
+12.3.4
+Encryption ................................................................................................................... 133
+12.3.5
+Integrity........................................................................................................................ 133
+12.3.6
+_PRIVATE ................................................................................................................... 133
+12.3.7
+TPM2B_PRIVATE ....................................................................................................... 133
+12.4 Identity Object ........................................................................................................................ 134
+12.4.1
+Description .................................................................................................................. 134
+12.4.2
+_ID_OBJECT .............................................................................................................. 134
+12.4.3
+TPM2B_ID_OBJECT .................................................................................................. 134
+13
+
+NV Storage Structures ...................................................................................................................... 135
+13.1 TPM_NV_INDEX ................................................................................................................... 135
+13.2 TPMA_NV (NV Index Attributes) ........................................................................................... 136
+13.3 TPMS_NV_PUBLIC ............................................................................................................... 139
+13.4 TPM2B_NV_PUBLIC ............................................................................................................. 139
+
+14
+
+Context Data ..................................................................................................................................... 140
+14.1 Introduction ............................................................................................................................ 140
+14.2 TPM2B_CONTEXT_SENSITIVE........................................................................................... 140
+14.3 TPMS_CONTEXT_DATA ...................................................................................................... 140
+14.4 TPM2B_CONTEXT_DATA .................................................................................................... 140
+14.5 TPMS_CONTEXT ................................................................................................................. 141
+14.6 Parameters of TPMS_CONTEXT .......................................................................................... 142
+14.6.1
+sequence ..................................................................................................................... 142
+14.6.2
+savedHandle ............................................................................................................... 142
+14.6.3
+hierarchy...................................................................................................................... 143
+14.7 Context Protection ................................................................................................................. 143
+14.7.1
+Context Integrity .......................................................................................................... 143
+14.7.2
+Context Confidentiality ................................................................................................ 143
+
+15
+
+Creation Data .................................................................................................................................... 144
+15.1 TPMS_CREATION_DATA .................................................................................................... 144
+15.2 TPM2B_CREATION_DATA .................................................................................................. 144
+
+Page viii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Annex A (informative) Algorithm Constants ............................................................................................. 145
+A.1
+Introduction ............................................................................................................................ 145
+A.2
+Allowed Hash Algorithms....................................................................................................... 145
+A.2.1
+SHA1 ........................................................................................................................... 145
+A.2.2
+SHA256 ....................................................................................................................... 145
+A.2.3
+SHA384 ....................................................................................................................... 145
+A.2.4
+SHA512 ....................................................................................................................... 146
+A.2.5
+SM3_256 ..................................................................................................................... 146
+A.3
+Architectural Limits ................................................................................................................ 146
+Annex B (informative) Implementation Definitions ................................................................................... 147
+B.1
+Introduction ............................................................................................................................ 147
+B.2
+Logic Values .......................................................................................................................... 147
+B.3
+Processor Values .................................................................................................................. 147
+B.4
+Implemented Algorithms ........................................................................................................ 148
+B.5
+Implemented Commands ...................................................................................................... 148
+B.6
+Algorithm Constants .............................................................................................................. 151
+B.6.1
+RSA ............................................................................................................................. 152
+B.6.2
+ECC ............................................................................................................................. 152
+B.6.3
+AES ............................................................................................................................. 152
+B.6.4
+SM4 ............................................................................................................................. 152
+B.6.5
+Symmetric ................................................................................................................... 153
+B.7
+Implementation Specific Values ............................................................................................ 154
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page ix
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Tables
+Table 1 — Name Prefix Convention ........................................................................................................... 15
+Table 2 — Unmarshaling Errors ................................................................................................................. 16
+Table 3 — Definition of Base Types ........................................................................................................... 17
+Table 4 — Definition of Types for Documentation Clarity ........................................................................... 17
+Table 5 — Definition of (UINT32) TPM_SPEC Constants <> ..................................................................... 18
+Table 6 — Definition of (UINT32) TPM_GENERATED Constants <O> ..................................................... 18
+Table 7 — Definition of (UINT16) TPM_ALG_ID Constants <IN/OUT, S> ................................................. 19
+Table 8 — Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants <IN/OUT, S> ............................ 22
+Table 9 — TPM Command Format Fields Description ............................................................................... 22
+Table 10 — Legend for Command Code Tables ........................................................................................ 23
+Table 11 — Definition of (UINT32) TPM_CC Constants (Numeric Order) <IN/OUT, S> ........................... 24
+Table 12 — Format-Zero Response Codes ................................................................................................ 30
+Table 13 — Format-One Response Codes ................................................................................................ 31
+Table 14 — Response Code Groupings ..................................................................................................... 31
+Table 15 — Definition of (UINT32) TPM_RC Constants (Actions) <OUT> ................................................ 32
+Table 16 — Definition of (INT8) TPM_CLOCK_ADJUST Constants <IN> ................................................. 37
+Table 17 — Definition of (UINT16) TPM_EO Constants <IN/OUT> ........................................................... 37
+Table 18 — Definition of (UINT16) TPM_ST Constants <IN/OUT, S> ....................................................... 38
+Table 19 — Definition of (UINT16) TPM_SU Constants <IN> .................................................................... 40
+Table 20 — Definition of (UINT8) TPM_SE Constants <IN> ...................................................................... 40
+Table 21 — Definition of (UINT32) TPM_CAP Constants .......................................................................... 41
+Table 22 — Definition of (UINT32) TPM_PT Constants <IN/OUT, S> ....................................................... 41
+Table 23 — Definition of (UINT32) TPM_PT_PCR Constants <IN/OUT, S> ............................................. 47
+Table 24 — Definition of (UINT32) TPM_PS Constants <OUT> ................................................................ 49
+Table 25 — Definition of Types for Handles ............................................................................................... 50
+Table 26 — Definition of (UINT8) TPM_HT Constants <S> ....................................................................... 50
+Table 27 — Definition of (UINT32) TPM_RH Constants <IN, S> ............................................................... 52
+Table 28 — Definition of (TPM_HANDLE) TPM_HC Constants <IN, S> ................................................... 54
+Table 29 — Definition of (UINT32) TPMA_ALGORITHM Bits .................................................................... 55
+Table 30 — Definition of (UINT32) TPMA_OBJECT Bits ........................................................................... 56
+Table 31 — Definition of (UINT8) TPMA_SESSION Bits <IN/OUT> .......................................................... 62
+Table 32 — Definition of (UINT8) TPMA_LOCALITY Bits <IN/OUT> ........................................................ 64
+Table 33 — Definition of (UINT32) TPMA_PERMANENT Bits <OUT> ...................................................... 64
+Table 34 — Definition of (UINT32) TPMA_STARTUP_CLEAR Bits <OUT> .............................................. 65
+Table 35 — Definition of (UINT32) TPMA_MEMORY Bits <Out> .............................................................. 66
+Table 36 — Definition of (TPM_CC) TPMA_CC Bits <OUT> ..................................................................... 67
+Table 37 — Definition of (BYTE) TPMI_YES_NO Type ............................................................................. 70
+
+Page x
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 38 — Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type........................................................ 70
+Table 39 — Definition of (TPM_HANDLE) TPMI_DH_PERSISTENT Type ............................................... 71
+Table 40 — Definition of (TPM_HANDLE) TPMI_DH_ENTITY Type <IN> ................................................ 71
+Table 41 — Definition of (TPM_HANDLE) TPMI_DH_PCR Type <IN> ..................................................... 72
+Table 42 — Definition of (TPM_HANDLE) TPMI_SH_AUTH_SESSION Type <IN/OUT> ........................ 72
+Table 43 — Definition of (TPM_HANDLE) TPMI_SH_HMAC Type <IN/OUT> .......................................... 72
+Table 44 — Definition of (TPM_HANDLE) TPMI_SH_POLICY Type <IN/OUT> ....................................... 72
+Table 45 — Definition of (TPM_HANDLE) TPMI_DH_CONTEXT Type .................................................... 73
+Table 46 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY Type ................................................ 73
+Table 47 — Definition of (TPM_HANDLE) TPMI_RH_ENABLES Type ..................................................... 73
+Table 48 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_AUTH Type <IN> ............................ 74
+Table 49 — Definition of (TPM_HANDLE) TPMI_RH_PLATFORM Type <IN> ......................................... 74
+Table 50 — Definition of (TPM_HANDLE) TPMI_RH_OWNER Type <IN> ............................................... 74
+Table 51 — Definition of (TPM_HANDLE) TPMI_RH_ENDORSEMENT Type <IN> ................................. 75
+Table 52 — Definition of (TPM_HANDLE) TPMI_RH_PROVISION Type <IN> ......................................... 75
+Table 53 — Definition of (TPM_HANDLE) TPMI_RH_CLEAR Type <IN> ................................................. 75
+Table 54 — Definition of (TPM_HANDLE) TPMI_RH_NV_AUTH Type <IN> ............................................ 76
+Table 55 — Definition of (TPM_HANDLE) TPMI_RH_LOCKOUT Type <IN> ........................................... 76
+Table 56 — Definition of (TPM_HANDLE) TPMI_RH_NV_INDEX Type <IN/OUT> .................................. 76
+Table 57 — Definition of (TPM_ALG_ID) TPMI_ALG_HASH Type............................................................ 77
+Table 58 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM Type ........................................................... 77
+Table 59 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM Type .............................................................. 78
+Table 60 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_OBJECT Type ............................................. 78
+Table 61 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_MODE Type ................................................. 79
+Table 62 — Definition of (TPM_ALG_ID) TPMI_ALG_KDF Type .............................................................. 79
+Table 63 — Definition of (TPM_ALG_ID) TPMI_ALG_SIG_SCHEME Type .............................................. 80
+Table 64 — Definition of (TPM_ALG_ID) TPMI_ECC_KEY_EXCHANGE Type ........................................ 80
+Table 65 — Definition of (TPM_ST) TPMI_ST_COMMAND_TAG Type .................................................... 80
+Table 66 — Definition of TPMS_ALGORITHM_DESCRIPTION Structure <OUT> .................................... 81
+Table 67 — Definition of TPMU_HA Union <IN/OUT, S> ........................................................................... 81
+Table 68 — Definition of TPMT_HA Structure <IN/OUT> .......................................................................... 82
+Table 69 — Definition of TPM2B_DIGEST Structure ................................................................................. 83
+Table 70 — Definition of TPM2B_DATA Structure ..................................................................................... 83
+Table 71 — Definition of Types for TPM2B_NONCE ................................................................................. 83
+Table 72 — Definition of Types for TPM2B_AUTH .................................................................................... 83
+Table 73 — Definition of Types for TPM2B_OPERAND ............................................................................ 84
+Table 74 — Definition of TPM2B_EVENT Structure ................................................................................... 84
+Table 75 — Definition of TPM2B_MAX_BUFFER Structure ...................................................................... 84
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xi
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Table 76 — Definition of TPM2B_MAX_NV_BUFFER Structure ............................................................... 84
+Table 77 — Definition of TPM2B_TIMEOUT Structure <IN/OUT> ............................................................. 85
+Table 78 — Definition of TPM2B_IV Structure <IN/OUT> .......................................................................... 85
+Table 79 — Definition of TPMU_NAME Union <> ...................................................................................... 85
+Table 80 — Definition of TPM2B_NAME Structure .................................................................................... 86
+Table 81 — Definition of TPMS_PCR_SELECT Structure ......................................................................... 87
+Table 82 — Definition of TPMS_PCR_SELECTION Structure ................................................................... 87
+Table 83 — Values for proof Used in Tickets ............................................................................................. 88
+Table 84 — General Format of a Ticket ...................................................................................................... 88
+Table 85 — Definition of TPMT_TK_CREATION Structure ........................................................................ 89
+Table 86 — Definition of TPMT_TK_VERIFIED Structure .......................................................................... 90
+Table 87 — Definition of TPMT_TK_AUTH Structure ................................................................................ 91
+Table 88 — Definition of TPMT_TK_HASHCHECK Structure .................................................................... 92
+Table 89 — Definition of TPMS_ALG_PROPERTY Structure <OUT> ....................................................... 92
+Table 90 — Definition of TPMS_TAGGED_PROPERTY Structure <OUT> ............................................... 92
+Table 91 — Definition of TPMS_TAGGED_PCR_SELECT Structure <OUT> ........................................... 93
+Table 92 — Definition of TPML_CC Structure ............................................................................................ 93
+Table 93 — Definition of TPML_CCA Structure <OUT> ............................................................................. 94
+Table 94 — Definition of TPML_ALG Structure .......................................................................................... 94
+Table 95 — Definition of TPML_HANDLE Structure <OUT>...................................................................... 94
+Table 96 — Definition of TPML_DIGEST Structure .................................................................................... 95
+Table 97 — Definition of TPML_DIGEST_VALUES Structure ................................................................... 95
+Table 98 — Definition of TPM2B_DIGEST_VALUES Structure ................................................................. 95
+Table 99 — Definition of TPML_PCR_SELECTION Structure ................................................................... 96
+Table 100 — Definition of TPML_ALG_PROPERTY Structure <OUT> ..................................................... 96
+Table 101 — Definition of TPML_TAGGED_TPM_PROPERTY Structure <OUT> ................................... 96
+Table 102 — Definition of TPML_TAGGED_PCR_PROPERTY Structure <OUT> ................................... 97
+Table 103 — Definition of {ECC} TPML_ECC_CURVE Structure <OUT> ................................................. 97
+Table 104 — Definition of TPMU_CAPABILITIES Union <OUT>............................................................... 97
+Table 105 — Definition of TPMS_CAPABILITY_DATA Structure <OUT> ................................................. 98
+Table 106 — Definition of TPMS_CLOCK_INFO Structure ........................................................................ 98
+Table 107 — Definition of TPMS_TIME_INFO Structure ........................................................................... 99
+Table 108 — Definition of TPMS_TIME_ATTEST_INFO Structure <OUT> ............................................. 100
+Table 109 — Definition of TPMS_CERTIFY_INFO Structure <OUT> ...................................................... 100
+Table 110 — Definition of TPMS_QUOTE_INFO Structure <OUT> ........................................................ 100
+Table 111 — Definition of TPMS_COMMAND_AUDIT_INFO Structure <OUT> ..................................... 101
+Table 112 — Definition of TPMS_SESSION_AUDIT_INFO Structure <OUT> ........................................ 101
+Table 113 — Definition of TPMS_CREATION_INFO Structure <OUT> .................................................. 101
+Table 114 — Definition of TPMS_NV_CERTIFY_INFO Structure <OUT> ............................................... 101
+Page xii
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 115 — Definition of (TPM_ST) TPMI_ST_ATTEST Type <OUT> .................................................. 102
+Table 116 — Definition of TPMU_ATTEST Union <OUT> ....................................................................... 102
+Table 117 — Definition of TPMS_ATTEST Structure <OUT> .................................................................. 103
+Table 118 — Definition of TPM2B_ATTEST Structure <OUT> ................................................................ 103
+Table 119 — Definition of TPMS_AUTH_COMMAND Structure <IN> ..................................................... 104
+Table 120 — Definition of TPMS_AUTH_RESPONSE Structure <OUT> ................................................ 104
+Table 121 — Definition of {AES} (TPM_KEY_BITS) TPMI_AES_KEY_BITS Type ................................. 105
+Table 122 — Definition of {SM4} (TPM_KEY_BITS) TPMI_SM4_KEY_BITS Type ................................. 105
+Table 123 — Definition of TPMU_SYM_KEY_BITS Union ....................................................................... 106
+Table 124 — Definition of TPMU_SYM_MODE Union ............................................................................. 106
+Table 125 — xDefinition of TPMU_SYM_DETAILS Union ....................................................................... 107
+Table 126 — Definition of TPMT_SYM_DEF Structure ............................................................................ 107
+Table 127 — Definition of TPMT_SYM_DEF_OBJECT Structure ............................................................ 107
+Table 128 — Definition of TPM2B_SYM_KEY Structure .......................................................................... 108
+Table 129 — Definition of TPMS_SYMCIPHER_PARMS Structure ........................................................ 108
+Table 130 — Definition of TPM2B_SENSITIVE_DATA Structure ............................................................ 108
+Table 131 — Definition of TPMS_SENSITIVE_CREATE Structure <IN> ................................................ 109
+Table 132 — Definition of TPM2B_SENSITIVE_CREATE Structure <IN, S> .......................................... 110
+Table 133 — Definition of TPMS_SCHEME_SIGHASH Structure ........................................................... 110
+Table 134 — Definition of (TPM_ALG_ID) TPMI_ALG_KEYEDHASH_SCHEME Type .......................... 110
+Table 135 — Definition of Types for HMAC_SIG_SCHEME .................................................................... 110
+Table 136 — Definition of TPMS_SCHEME_XOR Structure ................................................................... 111
+Table 137 — Definition of TPMU_SCHEME_KEYEDHASH Union <IN/OUT, S> .................................... 111
+Table 138 — Definition of TPMT_KEYEDHASH_SCHEME Structure ..................................................... 111
+Table 139 — Definition of {RSA} Types for RSA_SIG_SCHEMES .......................................................... 112
+Table 140 — Definition of {ECC} Types for ECC_SIG_SCHEMES.......................................................... 112
+Table 141 — Definition of {ECC} TPMS_SCHEME_ECDAA Structure .................................................... 112
+Table 142 — Definition of TPMU_SIG_SCHEME Union <IN/OUT, S> .................................................... 113
+Table 143 — Definition of TPMT_SIG_SCHEME Structure ..................................................................... 113
+Table 144 — Definition of {RSA} TPMS_SCHEME_OAEP Structure ...................................................... 114
+Table 145 — Definition of {ECC} TPMS_SCHEME_ECDH Structure ...................................................... 114
+Table 146 — Definition of TPMS_SCHEME_MGF1 Structure ................................................................. 114
+Table 147 — Definition of {ECC} TPMS_SCHEME_KDF1_SP800_56a Structure .................................. 114
+Table 148 — Definition of TPMS_SCHEME_KDF2 Structure .................................................................. 115
+Table 149 — Definition of TPMS_SCHEME_KDF1_SP800_108 Structure ............................................. 115
+Table 150 — Definition of TPMU_KDF_SCHEME Union <IN/OUT, S> ................................................... 115
+Table 151 — Definition of TPMT_KDF_SCHEME Structure .................................................................... 115
+Table 152 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM_SCHEME Type <> ................................. 116
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xiii
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Table 153 — Definition of TPMU_ASYM_SCHEME Union ...................................................................... 116
+Table 154 — Definition of TPMT_ASYM_SCHEME Structure <> ............................................................ 117
+Table 155 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_SCHEME Type .............................. 117
+Table 156 — Definition of {RSA} TPMT_RSA_SCHEME Structure ......................................................... 117
+Table 157 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_DECRYPT Type ............................ 118
+Table 158 — Definition of {RSA} TPMT_RSA_DECRYPT Structure ....................................................... 118
+Table 159 — Definition of {RSA} TPM2B_PUBLIC_KEY_RSA Structure ................................................ 118
+Table 160 — Definition of {RSA} (TPM_KEY_BITS) TPMI_RSA_KEY_BITS Type ................................. 119
+Table 161 — Definition of {RSA} TPM2B_PRIVATE_KEY_RSA Structure .............................................. 119
+Table 162 — Definition of {ECC} TPM2B_ECC_PARAMETER Structure ............................................... 120
+Table 163 — Definition of {ECC} TPMS_ECC_POINT Structure ............................................................. 120
+Table 164 — Definition of {ECC} TPM2B_ECC_POINT Structure ........................................................... 120
+Table 165 — Definition of (TPM_ALG_ID) {ECC} TPMI_ALG_ECC_SCHEME Type ............................. 121
+Table 166 — Definition of {ECC} (TPM_ECC_CURVE) TPMI_ECC_CURVE Type ................................ 121
+Table 167 — Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure .................. 121
+Table 168 — Definition of {ECC} TPMS_ALGORITHM_DETAIL_ECC Structure <OUT> ....................... 122
+Table 169 — Definition of {RSA} TPMS_SIGNATURE_RSASSA Structure ............................................ 122
+Table 170 — Definition of {RSA} TPMS_SIGNATURE_RSAPSS Structure ............................................ 123
+Table 171 — Definition of {ECC} TPMS_SIGNATURE_ECDSA Structure .............................................. 123
+Table 172 — Definition of TPMU_SIGNATURE Union <IN/OUT, S> ....................................................... 123
+Table 173 — Definition of TPMT_SIGNATURE Structure ........................................................................ 124
+Table 174 — Definition of TPMU_ENCRYPTED_SECRET Union <S> ................................................... 124
+Table 175 — Definition of TPM2B_ENCRYPTED_SECRET Structure .................................................... 125
+Table 176 — Definition of (TPM_ALG_ID) TPMI_ALG_PUBLIC Type .................................................... 126
+Table 177 — Definition of TPMU_PUBLIC_ID Union <IN/OUT, S> ......................................................... 127
+Table 178 — Definition of TPMS_KEYEDHASH_PARMS Structure........................................................ 127
+Table 179 — Definition of TPMS_ASYM_PARMS Structure <> .............................................................. 128
+Table 180 — Definition of {RSA} TPMS_RSA_PARMS Structure ............................................................ 128
+Table 181 — Definition of {ECC} TPMS_ECC_PARMS Structure ........................................................... 129
+Table 182 — Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S> ................................................ 129
+Table 183 — Definition of TPMT_PUBLIC_PARMS Structure ................................................................. 130
+Table 184 — Definition of TPMT_PUBLIC Structure ................................................................................ 130
+Table 185 — Definition of TPM2B_PUBLIC Structure .............................................................................. 131
+Table 186 — Definition of {RSA} TPM2B_PRIVATE_VENDOR_SPECIFIC Structure<> ........................ 131
+Table 187 — Definition of TPMU_SENSITIVE_COMPOSITE Union <IN/OUT, S> ................................. 132
+Table 188 — Definition of TPMT_SENSITIVE Structure .......................................................................... 132
+Table 189 — Definition of TPM2B_SENSITIVE Structure <IN/OUT> ...................................................... 132
+Table 190 — Definition of _PRIVATE Structure <> .................................................................................. 133
+Table 191 — Definition of TPM2B_PRIVATE Structure <IN/OUT, S> ..................................................... 133
+Page xiv
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 192 — Definition of _ID_OBJECT Structure <> .............................................................................. 134
+Table 193 — Definition of TPM2B_ID_OBJECT Structure <IN/OUT> ..................................................... 134
+Table 194 — Definition of (UINT32) TPM_NV_INDEX Bits <> ................................................................. 135
+Table 195 — Options for space Field of TPM_NV_INDEX ....................................................................... 136
+Table 196 — Definition of (UINT32) TPMA_NV Bits ................................................................................ 137
+Table 197 — Definition of TPMS_NV_PUBLIC Structure ......................................................................... 139
+Table 198 — Definition of TPM2B_NV_PUBLIC Structure ....................................................................... 139
+Table 199 — Definition of TPM2B_CONTEXT_SENSITIVE Structure <IN/OUT> ................................... 140
+Table 200 — Definition of TPMS_CONTEXT_DATA Structure <IN/OUT, S> .......................................... 140
+Table 201 — Definition of TPM2B_CONTEXT_DATA Structure <IN/OUT> ............................................ 140
+Table 202 — Definition of TPMS_CONTEXT Structure ........................................................................... 141
+Table 203 — Context Handle Values ........................................................................................................ 142
+Table 204 — Definition of TPMS_CREATION_DATA Structure <OUT> ................................................. 144
+Table 205 — Definition of TPM2B_CREATION_DATA Structure <OUT> ............................................... 144
+Table 206 — Defines for SHA1 Hash Values ........................................................................................... 145
+Table 207 — Defines for SHA256 Hash Values ....................................................................................... 145
+Table 208 — Defines for SHA384 Hash Values ....................................................................................... 145
+Table 209 — Defines for SHA512 Hash Values ....................................................................................... 146
+Table 210 — Defines for SM3_256 Hash Values ..................................................................................... 146
+Table 211 — Defines for Architectural Limits Values ............................................................................... 146
+Table 212 — Defines for Logic Values ..................................................................................................... 147
+Table 213 — Defines for Processor Values .............................................................................................. 147
+Table 214 — Defines for Implemented Algorithms ................................................................................... 148
+Table 215 — Defines for Implemented Commands .................................................................................. 149
+Table 216 — Defines for RSA Algorithm Constants ................................................................................. 152
+Table 217 — Defines for ECC Algorithm Constants ................................................................................. 152
+Table 218 — Defines for AES Algorithm Constants ................................................................................. 152
+Table 219 — Defines for SM4 Algorithm Constants ................................................................................. 152
+Table 220 — Defines for Symmetric Algorithm Constants ....................................................................... 153
+Table 221 — Defines for Implementation Values ..................................................................................... 154
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page xv
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Figures
+Figure 1 — Command Format .................................................................................................................... 22
+Figure 2 — Format-Zero Response Codes ................................................................................................. 29
+Figure 3 — Format-One Response Codes ................................................................................................. 30
+Figure 4 — TPM 1.2 TPM_NV_INDEX ..................................................................................................... 135
+Figure 5 — TPM 2.0 TPM_NV_INDEX ..................................................................................................... 135
+
+Page xvi
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Trusted Platform Module Library
+Part 2: Structures
+1
+
+Scope
+
+This part of the Trusted Platform Module Library specification contains the definitions of the constants,
+flags, structure, and union definitions used to communicate with the TPM. Values defined in this
+document are used by the TPM commands defined in part 3: Commands and by the functions in part 4:
+Supporting Routines.
+NOTE
+
+2
+
+The structures in this document are the canonical form of the structures on the interface. All structures
+are "packed" with no octets of padding between structure elements. The TPM-internal form of the
+structures is dependent on the processor and compiler for the TPM implementation.
+
+Terms and definitions
+
+For the purposes of this document, the terms and definitions given in part 1 of this specification apply.
+3
+
+Symbols and abbreviated terms
+
+For the purposes of this document, the symbols and abbreviated terms given in part 1 apply.
+4
+4.1
+
+Notation
+Introduction
+
+The information in this document is formatted so that it may be converted to standard computer-language
+formats by an automated process. The purpose of this automated process is to minimize the transcription
+errors that often occur during the conversion process.
+For the purposes of this document, the conventions given in Part 1 apply.
+In addition, the conventions and notations in this clause describe the representation of various data so
+that it is both human readable and amenable to automated processing.
+When a table row contains the keyword “reserved” (all lower case) in columns 1 or 2, the tools will not
+produce any values for the row in the table.
+NOTE 1
+
+In the examples in this clause 4, the unmarshaling routines are shown as returning bool. In the code of
+the reference implementation, the return value is a TPM_RC. A bool is used in the examples, because
+the meaning of a TPM_RC is not yet defined.
+
+NOTE 2
+
+The unmarshaling code examples are the actual code that would be produced by the automatic code
+generator used in the construction of the reference code. The actual code contains additional parameter
+checking that is omitted for clarity of the principle being illustrated. Actual examples of the code are found
+in Part 4.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 1
+October 31, 2013
+
+ Part 2: Structures
+4.2
+
+Trusted Platform Module Library
+
+Named Constants
+
+A named constant is a numeric value to which a name has been assigned. In the C language, this is done
+with a #define statement. In this specification, a named constant is defined in a table that has a title that
+starts with “Definition” and ends with “Constants.”
+The table title will indicate the name of the class of constants that are being defined in the table. The title
+will include the data type of the constants in parentheses.
+The table in Example 1 names a collection of 16-bit constants and Example 2 shows the C code that
+might be produced from that table by an automated process.
+NOTE
+
+A named constant (#define) has no data type in C and an enumeration would be a better choice for
+many of the defined constants. However, the C language does not allow an enumerated type to have a
+storage type other than int so the method of using a combination of typedef and #define is used.
+
+EXAMPLE 1
+
+Table xx — Definition of (UINT16) COUNTING Constants
+Parameter
+
+Value
+
+Description
+
+first
+
+1
+
+decimal value is implicitly the size of the
+
+second
+
+0x0002
+
+hex value will match the number of bits in the constant
+
+third
+
+3
+
+fourth
+
+0x0004
+
+EXAMPLE 2
+/* The C language equivalent of the constants from the table above */
+typedef
+UINT16
+COUNTING;
+#define
+first
+1
+#define
+second
+0x0002
+#define
+third
+3
+#define
+fourth
+0x0004
+
+Page 2
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+4.3
+
+Part 2: Structures
+
+Data Type Aliases (typedefs)
+
+When a group of named items is assigned a type, it is placed in a table that has a title starting with
+“Definition of Types.” In this specification, defined types have names that use all upper-case characters.
+The table in Example 1 shows how typedefs would be defined in this specification and Example 2 shows
+the C-compatible code that might be produced from that table by an automated process.
+EXAMPLE 1
+
+Table xx — Definition of Types for Some Purpose
+Type
+
+Name
+
+Description
+
+unsigned short
+
+UINT16
+
+UINT16
+
+SOME_TYPE
+
+unsigned long
+
+UINT32
+
+UINT32
+
+LAST_TYPE
+
+EXAMPLE 2
+/* C language equivalent of the typedefs from the table above */
+typedef unsigned short
+UINT16;
+typedef UINT16
+SOME_TYPE;
+typedef unsigned long
+UINT32;
+typedef UINT32
+LAST_TYPE;
+
+4.4
+
+Enumerations
+
+A table that defines an enumerated data type will start with the word “Definition” and end with “Values.”
+A value in parenthesis will denote the intrinsic data size of the value and may have the values "INT8",
+"UINT8", "INT16", “UINT16”, "INT32", and “UINT32.” If this value is not present, “UINT16” is assumed.
+Most C compilers set the type of an enumerated value to be an integer on the machine – often 16 bits –
+but this is not always consistent. To ensure interoperability, the enumeration values may not exceed
+32,384.
+The table in Example 1 shows how an enumeration would be defined in this specification. Example 2
+shows the C code that might be produced from that table by an automated process.
+EXAMPLE 1
+
+Table xx — Definition of (UINT16) CARD_SUIT Values
+Suit Names
+
+Value
+
+CLUBS
+
+0x0000
+
+DIAMONDS
+
+0x000D
+
+HEARTS
+
+0x001A
+
+SPADES
+
+Description
+
+0x0027
+
+EXAMPLE 2
+/* C language equivalent of the structure defined in the table above */
+typedef enum {
+CLUBS
+=
+0x0000,
+DIAMONDS
+=
+0x000D,
+HEARTS
+=
+0x001A,
+SPADES
+=
+0x0027
+} CARD_SUIT;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 3
+October 31, 2013
+
+ Part 2: Structures
+4.5
+
+Trusted Platform Module Library
+
+Interface Type
+
+An interface type is used for an enumeration that is checked by the unmarshaling code. This type is
+defined for purposes of automatic generation of the code that will validate the type. The title will start with
+the keyword “Definition” and end with the keyword “Type.” A value in parenthesis indicates the base type
+of the interface. The table may contain an entry that is prefixed with the “#” character to indicate the
+response code if the validation code determines that the input parameter is the wrong type.
+EXAMPLE 1
+
+Table xx — Definition of (CARD_SUIT) RED_SUIT Type
+Values
+
+Comments
+
+HEARTS
+DIAMONDS
+#TPM_RC_SUIT
+
+response code returned when the unmarshaling of this type fails
+NOTE
+
+TPM_RC_SUIT is an example and no such response
+code is actually defined in this specification.
+
+EXAMPLE 2
+/* Validation code that might be automatically generated from table above */
+if((*target != HEARTS) && (*target != DIAMONDS))
+return TPM_RC_SUIT;
+
+In some cases, the allowed values are numeric values with no associated mnemonic. In such a case, the
+list of numeric values may be given a name. Then, when used in an interface definition, the name would
+have a "$" prefix to indicate that a named list of values should be substituted.
+To illustrate, assume that the implementation only supports two sizes (1024 and 2048 bits) for keys
+associated with some algorithm (MY algorithm). In the implementation section (Annex B a named list
+would be created.
+EXAMPLE 3
+
+Table xx — Defines for MY Algorithm Constants
+Name
+
+Value
+
+Comments
+
+MY_KEY_SIZES_BITS
+
+{1024, 2048}
+
+braces because this is a list value
+
+Page 4
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Then, whenever an input value would need to be a valid MY key size for the implementation, the value
+$MY_KEY_SIZES_BITS could be used. Given the definition for MY_KEY_SIZES_BITS in example 3
+above, the tables in example 4 and 5 below, are equivalent.
+EXAMPLE 4
+
+Table xx — Definition of (UINT16) MY_KEY_BITS Type
+Parameter
+
+Description
+
+{1024, 2048}
+
+the number of bits in the supported key
+
+EXAMPLE 5
+
+Table xx — Definition of (UINT16) MY_KEY_BITS Type
+Parameter
+$MY_KEY_SIZES_BITS
+
+4.6
+
+Description
+the number of bits in the supported key
+
+Arrays
+
+Arrays are denoted by a value in square brackets (“[ ]”) following a parameter name. The value in the
+brackets may be either an integer value such as “[20]” or the name of a component of the same structure
+that contains the array.
+The table in Example 1 shows how a structure containing fixed and variable-length arrays would be
+defined in this specification. Example 2 shows the C code that might be produced from that table by an
+automated process.
+EXAMPLE 1
+
+Table xx — Definition of A_STRUCT Structure
+Parameter
+
+Type
+
+Description
+
+array1[20]
+
+UINT16
+
+an array of 20 UINT16s
+
+a_size
+
+UINT16
+
+array2[a_size]
+
+UINT32
+
+an array of UINT32 values that has a
+number of elements determined by a_size
+above
+
+EXAMPLE 2
+/* C language equivalent of the typedefs from the table above */
+typedef struct {
+UINT16
+array1[20];
+UINT16
+a_size;
+UINT32
+array2[];
+} A_STRUCT;
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 5
+October 31, 2013
+
+ Part 2: Structures
+
+4.7
+
+Trusted Platform Module Library
+
+Structure Definitions
+
+The tables used to define structures have a title that starts with the word “Definition” and ends with
+“Structure.” The first column of the table will denote the reference names for the structure members; the
+second column the data type of the member; and the third column a synopsis of the use of the element.
+The table in Example 1 shows an example of how a structure would be defined in this specification and
+Example 2 shows the C code that might be produced from the table by an automated process. Example 3
+illustrates the type of unmarshaling code that could be generated using the information available in the
+table.
+EXAMPLE 1
+
+Table xx — Definition of SIMPLE_STRUCTURE Structure
+Parameter
+
+Type
+
+Description
+
+tag
+
+TPM_ST
+
+value1
+
+INT32
+
+value2
+
+INT32
+
+EXAMPLE 2
+/* C language equivalent of the structure defined in the table above */
+typedef struct {
+TPM_ST
+tag;
+INT32
+value1
+INT32
+value2;
+} SIMPLE_STRUCTURE;
+EXAMPLE 3
+bool SIMPLE_STRUCTURE_Unmarshal(SIMPLE_STRUCTURE *target, BYTE **buffer, INT32 *size)
+{
+// If unmarshal of tag succeeds
+if(TPM_ST_Unmarshal((TPM_ST *)&(target->tag), buffer, size))
+// then umarshal value1, and if that succeeds...
+if(INT32_Unmarshal((INT32 *)&(target->value1, buffer, size))
+// then return the results of unmarshaling values
+return(INT32_Unmarshal((INT32 *)&(target->value2, buffer, size))
+// if unmarshal of tag or value failed, return failure
+return FALSE;
+}
+
+Page 6
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+4.8
+
+Part 2: Structures
+
+Conditional Types
+
+An enumeration may contain an extended value indicated by “+” preceding the name in the "Value"
+column. This “+” indicates that this is a conditional value that may be allowed in certain situations.
+NOTE
+
+In many cases, the input values are algorithm IDs. When two collections of algorithm IDs differ only
+because one collection allows TPM_ALG_NULL and the other does not, it is preferred that the re not be
+two completely different enumerations because this leads to many casts. To avoid this, the “+” can be
+added to a TPM_ALG_NULL value in the table defining the type. When the use of that type allows
+TPM_ALG_NULL to be in the set, the use would append a “+” to the instance.
+
+EXAMPLE
+
+Table xx — Definition of (CARD_SUIT) TPMI_CARD_SUIT Type
+Values
+
+Comments
+
+SPADES
+HEARTS
+DIAMONDS
+CLUBS
++JOKER
+
+an optional value that may be allowed
+
+#TPM_RC_SUIT
+
+response code returned when the input value is not one of the
+values above
+
+When an interface type is used, a “+” will be appended to the type specification for the parameter when
+the conditional value is allowed. If no “+” is present, then the conditional value is not allowed.
+EXAMPLE 1
+
+Table xx — Definition of POKER_CARD Structure
+Parameter
+
+Type
+
+Description
+
+suit
+
+TPMI_CARD_SUIT+
+
+allows joker
+
+number
+
+UINT8
+
+the card value
+
+EXAMPLE 2
+
+Table xx — Definition of BRIDGE_CARD Structure
+Parameter
+
+Type
+
+Description
+
+suit
+
+TPMI_CARD_SUIT
+
+does not allow joker
+
+number
+
+UINT8
+
+the card value
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 7
+October 31, 2013
+
+ Part 2: Structures
+4.9
+
+Trusted Platform Module Library
+
+Unions
+
+4.9.1
+
+Introduction
+
+A union allows a structure to contain a variety of structures or types. The union has members, only one of
+which is present at a time. Three different tables are required to fully characterize a union so that it may
+be communicated on the TPM interface and used by the TPM:
+1) union definition;
+2) union instance; and
+3) union selector definition.
+4.9.2
+
+Union Definition
+
+The table in Example 1 illustrates a union definition. The title of a union definition table starts with
+“Definition” and ends with “Union.” The “Parameter” column of a union definition lists the different names
+that are used when referring a specific type. The “Type” column identifies the data type of the member.
+The “Selector” column identifies the value that is used by the marshaling and unmarshaling code to
+determine which case of the union is present.
+If a parameter is the keyword “null,” then this denotes a selector with no contents. The table in Example 1
+illustrates a union in which a conditional null selector is allowed to indicate an empty union member.
+Example 2 shows how the table would be converted into C-compatible code.
+The expectation is that the unmarshaling code for the union will validate that the selector for the union is
+one of values in the selector list.
+EXAMPLE 1
+
+Table xx — Definition of NUMBER_UNION Union
+Parameter
+
+Type
+
+Selector
+
+a_byte
+
+BYTE
+
+BYTE_SELECT
+
+an_int
+
+int
+
+INT_SELECT
+
+a_float
+
+float
+
+FLOAT_SELECT
+
++null
+
+NULL_SELECT
+
+Description
+
+the empty branch
+
+EXAMPLE 2
+// C-compatible version of the union defined in the table above
+typedef union {
+BYTE
+a_byte;
+int
+an_int;
+float
+a_float;
+} NUMBER_UNION;
+EXAMPLE 3
+
+Page 8
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+// Possible auto-generated code to unmarshal a union in Example 2 based on the
+// input value of selector
+bool NUMBER_UNION_Unmarshal(NUMBER_UNION *target, BYTE **buffer,
+INT32 *size, UINT32 selector)
+{
+switch (selector) {
+case BYTE_SELECT:
+return BYTE_Unmarshal((BYTE *)&(target->a_byte), buffer, size);
+case INT_SELECT:
+return INT_Unmarshal((int *)&(target->an_int), buffer, size);
+case FLOAT_SELECT:
+return FLOAT_Unmarshal((float *)&(target->a_float), buffer, size);
+case NULL_SELECT:
+return;
+}
+
+A table may have a type with no selector. This is used when the first part of the structure for all union
+members is identical. This type is a programming convenience, allowing code to reference the common
+members without requiring a case statement to determine the specific structure. In object oriented
+programming terms, this type is a superclass and the types with selectors are subclasses.
+4.9.3
+
+Union Instance
+
+When a union is used in a structure that is sent on the interface, the structure will minimally contain a
+selector and a union. The selector value indicates which of the possible union members is present so that
+the unmarshaling code can unmarshal the correct type. The selector may be any of the parameters that
+occur in the structure before the union instance. To denote the structure parameter that is used as the
+selector, its name is in brackets (“[ ]”) placed before the parameter name associated with the union.
+The table in Example 1 shows the definition of a structure that contains a union and a selector. Example 2
+shows how the table would be converted into C-compatible code and Example 3 shows how the
+unmarshaling code would handle the selector.
+EXAMPLE 1
+
+Table xx — Definition of STRUCTURE_WITH_UNION Structure
+Parameter
+
+Type
+
+Description
+
+select
+
+NUMBER_SELECT
+
+a value indicating the type in number
+
+[select] number
+
+NUMBER_UNION
+
+a union as shown in 4.9.2
+
+EXAMPLE 2
+// C-compatible version of the union structure in the table above
+typedef struct {
+NUMBER_SELECT
+select;
+NUMBER_UNION
+number;
+} STRUCT_WITH_UNION;
+EXAMPLE 3
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 9
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+// Possible unmarshaling code for the structure above
+bool STRUCT_WITH_UNION_Unmarshal(STRUCT_WITH_UNION *target, BYTE **buffer, INT32 *size)
+{
+// Unmarshal the selector value
+if(!NUMBER_SELECT_Unmarshal((NUMBER_SELECT *)&target->select, buffer, size))
+return FALSE;
+// Use the unmarshaled selector value to indicate to the union unmarshal
+// function which unmarshaling branch to follow.
+return(NUMBER_UNION_Unmarshal((NUMBER_UNION *)&(target->number),
+buffer, size, (UINT32)target->select);
+}
+
+4.9.4
+
+Union Selector Definition
+
+The selector definition limits the values that are used in unmarshaling a union. Two different selector sets
+applied to the same union define different types.
+For the union in 4.9.2, a selector definition should be limited to no more than four values, one for each of
+the union members. The selector definition could have fewer than four values.
+In Example 1, the table defines a value for each of the union members.
+EXAMPLE 1
+
+Table xx — Definition of (INT8) NUMBER_SELECT Values <IN>
+Name
+
+Value
+
+BYTE_SELECT
+
+3
+
+INT_SELECT
+
+2
+
+FLOAT_SELECT
+
+1
+
+NULL_SELECT
+
+Comments
+
+0
+
+The unmarshaling code would limit the input values to the defined values. When the NUMBER_SELECT
+is used in the union instance of 4.9.3, any of the allowed union members of NUMBER_UNION could be
+present.
+A different selection could be used to limit the values in a specific instance. To get the different selection,
+a new structure is defined with a different selector. The table in example 2 illustrates a way to subset the
+union. The base type of the selection is NUMBER_SELECT so a NUMBER_SELECT will be unmarshaled
+before the checks are made to see if the value is in the correct range for JUST_INTEGERS types. If the
+base type had been UINT8, then no checking would occur prior to checking that the value is in the
+allowed list. In this particular case, the effect is the same in either case since the only values that will be
+accepted by the unmarshaling code for JUST_INTEGER are BYTE_SELECT and INT_SELECT.
+EXAMPLE 2
+
+Table xx — Definition of (NUMBER_SELECT) AN_INTEGER Type <IN>
+Values
+{BYTE_SELECT, INT_SELECT}
+NOTE
+
+Comments
+list of allowed values
+
+Since NULL_SELECT is not in the list of values accepted as a JUST_INTEGER, the “+” modifier will have
+no effect if used for a JUST_INTEGERS type shown in Example 3.
+
+Page 10
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+The selector in Example 2 can then be used in a subset union as shown in Example 3.
+EXAMPLE 3
+
+Table xx — Definition of JUST_INTEGERS Structure
+Parameter
+
+Type
+
+Description
+
+select
+
+AN_INTEGER
+
+a value indicating the type in number
+
+[select] number
+
+NUMBER_UNION
+
+a union as shown in 4.9.2
+
+4.10 Bit Field Definitions
+A table that defines a structure containing bit fields has a title that starts with “Definition” and ends with
+“Bits.” A type identifier in parentheses in the title indicates the size of the datum that contains the bit
+fields.
+When the bit fields do not occupy consecutive locations, a spacer field is defined with a name of
+“Reserved.” Bits in these spaces are reserved and shall be zero.
+The table in Example 1 shows how a structure containing bit fields would be defined in this specification.
+Example 2 shows the C code that might be produced from that table by an automated process.
+When a field has more than one bit, the range is indicated by a pair of numbers separated by a colon (“:”).
+The numbers will be in high:low order.
+EXAMPLE1
+
+Table xx — Definition of (UINT32) SOME_ATTRIBUTE Bits
+Bit
+0
+
+Name
+
+Action
+
+zeroth_bit
+
+SET (1): what to do if bit is 1
+CLEAR (0): what to do if bit is 0
+
+1
+
+first_bit
+
+SET (1): what to do if bit is 1
+CLEAR (0): what to do if bit is 0
+
+6:2
+7
+
+Reserved
+
+A placeholder that spans 5 bits
+
+third_bit
+
+SET (1): what to do if bit is 1
+CLEAR (0): what to do if bit is 0
+
+31:8
+
+Reserved
+
+Placeholder to fill 32 bits
+
+EXAMPLE 2
+/* C language equivalent of the attributes structure defined in the table above */
+typedef struct {
+int zeroth_bit : 1;
+int first_bit : 1;
+int Reserved3 : 5;
+int third_bit : 1;
+int Reserved7 : 24;
+} SOME_ATTRIBUTE;
+
+4.11 Parameter Limits
+A parameter used in a structure may be given a set of values that can be checked by the unmarshaling
+code. The allowed values for a parameter may be included in the definition of the parameter by
+appending the values and delimiting them with braces (“{ }”). The values are comma-separated
+expressions. A range of numbers may be indicated by separating two expressions with a colon (“:”). The
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 11
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+first number is an expression that represents the minimum allowed value and the second number
+indicates the maximum. If the minimum or maximum value expression is omitted, then the range is openended.
+Parameter limits expressed using braces apply only to inputs to the TPM. Any value returned by the
+TPM is assumed to be valid.
+The maximum size of an array may be indicated by putting a “{}” delimited expression following the
+square brackets (“[ ]”) that indicate that the value is an array.
+EXAMPLE
+
+Table xx — Definition of B_STRUCT Structure
+Parameter
+
+Type
+
+Description
+
+value1 {20:25}
+
+UINT16
+
+a parameter that must have a value between 20
+and 25
+
+value2 {20}
+
+UINT16
+
+a parameter that must have a value of 20
+
+value3 {:25}
+
+INT16
+
+a parameter that may be no larger than 25
+Since the parameter is signed, the minimum value
+is the largest negative integer that may be
+expressed in 16 bits.
+
+value4 {20:}
+
+a parameter that must be at least 20
+
+value5 {1,2,3,5}
+
+UINT16
+
+a parameter that may only have one of the four
+listed values
+
+value6 {1, 2, 10:(10+10)}
+
+UINT32
+
+a parameter that may have a value of 1, 2, or be
+between 10 and 20
+
+array1[value1]
+
+BYTE
+
+Because the index refers to value1, which is a
+value limited to be between 20 and 25 inclusive,
+array1 is an array that may have between 20 and
+25 octets. This is not the preferred way to indicate
+the upper limit for an array as it does not indicate
+the upper bound of the size.
+NOTE
+
+array2[value4]{:25}
+
+BYTE
+
+This is a limitation of the current
+parser. A different parser could
+associate the range of value1 with this
+value and compute the maximum size
+of the array.
+
+an array that may have between 20 and 25 octets
+This arrangement is used to allow the automatic
+code generation to allocate 25 octets to store the
+largest array2 that can be unmarshaled. The code
+generation can determine from this expression that
+value4 shall have a value of 25 or less. From the
+definition of value4 above, it can determine that
+value4 must have a value of at least 20.
+
+Page 12
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+4.12 Enumeration Macro
+An enumeration can be a list of allowed numeric values. For example, the allowed sizes for an RSA key
+might be expressed as:
+
+4.13 Size Checking
+In some structures, a size field is present to indicate the number of octets in some subsequent part of the
+structure. In the B_STRUCT table in 4.11, value4 indicates how many octets to unmarshal for array2. This
+semantic applies when the size field determines the number of octets to unmarshal. However, in some
+cases, the subsequent structure is self-defining. If the size precedes a parameter that is not an octet
+array, then the unmarshaled size of that parameter is determined by its data type. The table in Example 1
+shows a structure where the size parameter would nominally indicate the number of octets in the
+remainder of the structure.
+EXAMPLE 1
+
+Table xx — Definition of C_STRUCT Structure
+Parameter
+
+Type
+
+Comments
+
+size
+
+UINT16
+
+the expected size of the remainder of the structure
+
+anInteger
+
+UINT32
+
+a 4-octet value
+
+In this particular case, the value of size would be incorrect if it had any value other than 4. So that the
+table parser is able to know that the purpose of the size parameter is to define the number of octets
+expected in the remainder of the structure, an equal sign (“=”) is appended to the parameter name.
+In the example below, the size= causes the parser to generate validation code that will check that the
+unmarshaled size of someStructure and someData adds to the value unmarshaled for size. When the “=”
+decoration is present, a value of zero is not allowed for the size.
+EXAMPLE 2
+
+Table xx — Definition of D_STRUCT Structure
+Parameter
+
+Type
+
+Comments
+
+size=
+
+UINT16
+
+the size of a structure
+The “=” indicates that the TPM is required to
+validate that the remainder of the D_STRUCT
+structure is exactly the value in size. That is, the
+number of bytes in the input buffer used to
+successfully unmarshal someStructure must be the
+same as size.
+
+someStructure
+
+A_STRUCT
+
+a structure to be unmarshaled
+The size of the structure is computed when it is
+unmarshaled. Because an “=” is present on the
+definition of size, the TPM is required to validate
+that the unmarshaled size exactly matches size.
+
+someData
+
+Family “2.0”
+Level 00 Revision 00.99
+
+UINT32
+
+a value
+
+Published
+Copyright © TCG 2006-2013
+
+Page 13
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+4.14 Data Direction
+A structure or union may be input (IN), output (OUT), or internal. An input structure is sent to the TPM and
+is unmarshaled by the TPM. An output structure is sent from the TPM and is marshaled by the TPM. An
+internal structure is not used outside of the TPM except that it may be included in a saved context.
+By default, structures are assumed to be both IN and OUT and the code generation tool will generate
+both marshaling and unmarshaling code for the structure. This default may be changed by using values
+enclosed in angle brackets (“<>”) as part of the table title. If the angle brackets are empty, then the
+structure is internal and neither marshaling nor unmarshaling code is generated. If the angle brackets
+contain the letter “I” (such as in “IN” or “in” or “i”), then the structure is input and unmarshaling code will be
+generated. If the angle brackets contain the letter “O” (such as in “OUT” or “out” or “o”), then the structure
+is output and marshaling code will be generated.
+EXAMPLE 1
+
+Both of the following table titles would indicate a structure that is used in both input and output
+Table xx — Definition of TPMS_A Structure
+Table xx — Definition of TPMS_A Structure <IN/OUT>
+
+EXAMPLE 2
+
+The following table title would indicate a structure that is used only for input
+Table xx — Definition of TPMS_A Structure <IN>
+
+EXAMPLE 3
+
+The following table title would indicate a structure that is used only for output
+Table xx — Definition of TPMS_A Structure <OUT>
+
+4.15 Structure Validations
+By default, when a structure is used for input to the TPM, the code generation tool will generate the
+unmarshaling code for that structure. Auto-generation may be suppressed by adding an “S” within the
+angle brackets.
+EXAMPLE
+
+The following table titles indicate a structure for which the auto -generation of the validation code is to be
+suppressed.
+Table xx — Definition of TPMT_A Structure <S>
+Table xx — Definition of TPMT_A Structure <IN, S>
+Table xx — Definition of TPMT_A Structure <IN/OUT, S>
+
+4.16 Name Prefix Convention
+Parameters are constants, variables, structures, unions, and structure members. Structure members are
+given a name that is indicative of its use, with no special prefix. The other parameter types are named
+according to their type with their name starting with “TPMx_”, where “x” is an optional character to indicate
+the data type.
+In some cases, additional qualifying characters will follow the underscore. These are generally used when
+dealing with an enumerated data type.
+TPMA_ This is an attribute structure, where bits are associated with particular attributes
+
+Page 14
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 1 — Name Prefix Convention
+Prefix
+
+Description
+
+_TPM_
+
+an indication/signal from the TPM’s system interface
+
+TPM_
+
+a constant or an enumerated type
+
+TPM2_
+
+a command defined by this specification
+
+TPM2B_
+
+a structure that is a sized buffer where the size of the buffer is contained in a 16-bit, unsigned
+value
+The first parameter is the size in octets of the second parameter. The second parameter may be
+any type.
+
+TPMA_
+
+a structure where each of the fields defines an attribute and each field is usually a single bit
+All the attributes in an attribute structure are packed with the overall size of the structure
+indicated in the heading of the attribute description (UINT8, UINT16, or UINT32).
+
+TPM_ALG_
+
+an enumerated type that indicates an algorithm
+A TPM_ALG_ is often used as a selector for a union.
+
+TPMI_
+
+an interface type
+The value is specified for purposes of dynamic type checking when unmarshaled.
+
+TPML_
+
+a list length followed by the indicated number of entries of the indicated type
+This is an array with a length field.
+
+TPMS_
+
+a structure that is not a size buffer or a tagged buffer or a list
+
+TPMT_
+
+a structure with the first parameter being a structure tag, indicating the type of the structure that
+follows
+A structure tag may be either a TPMT_ST_ or TPM_ALG_ depending on context.
+
+TPMU_
+
+a union of structures, lists, or unions
+If a union exists, there will normally be a companion TPMT_ that is the expression of the union
+in a tagged structure, where the tag is the selector indicating which member of the union is
+present.
+
+TPM_xx_
+
+an enumeration value of a particular type
+The value of “xx” will be indicative of the use of the enumerated type. A table of “TPM_xx”
+constant definitions will exist to define each of the TPM_xx_ values.
+EXAMPLE 1
+
+TPM_CC_ indicates that the type is used for a commandCode. The allowed enumeration
+values will be found in the table defining the TPM_CC constants (Table 11).
+
+EXAMPLE 2
+
+TPM_RC_ indicates that the type is used for a responseCode. The allowed enumeration
+values are in Table 15.
+
+4.17 Data Alignment
+The data structures in this Part 2 use octet alignment for all structures. When used in a table to indicate a
+maximum size, the sizeof() function returns the octet-aligned size of the structure, with no padding.
+4.18
+
+Parameter Unmarshaling Errors
+
+The TPM commands are defined in Part 3. The command definition included C code that details the
+actions performed by that command. The code is written assuming that the parameters of the command
+have been unmarshaled.
+NOTE 1
+
+An implementation is not required to process parameters in this manner or to separate the parameter
+parsing from the command actions. This method was chosen for the specification so that the normative
+behavior described by the detailed actions would be clear and unencumbered.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 15
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Unmarshaling is the process of processing the parameters in the input buffer and preparing the
+parameters for use by the command-specific action code. No data movement need take place but it is
+required that the TPM validate that the parameters meet the requirements of the expected data type as
+defined in this Part 2.
+When an error is encountered while unmarshaling a command parameter, an error response code is
+returned and no command processing occurs. A table defining a data type may have response codes
+embedded in the table to indicate the error returned when the input value does not match the parameters
+of the table.
+EXAMPLE 1
+
+Table 11 has a listing of TPM command code values. The last row in the table contains
+"#TPM_RC_COMMAND_CODE" indicating the response code that is returned if the TPM is unmarshaling
+a value that it expects to be a TPM_CC and the input value is not in the table.
+
+NOTE 2
+
+In the reference implementation, a parameter number is added to the response code so that the offending
+parameter can be isolated.
+
+In many cases, the table contains no specific response code value and the return code will be determined
+as defined in Table 2.
+Table 2 — Unmarshaling Errors
+Response code
+
+Usage
+
+TPM_RC_INSUFFICIENT
+
+the input buffer did not contain enough octets to allow unmarshaling of the
+expected data type;
+
+TPM_RC_RESERVED
+
+a non-zero value was found in a reserved field of an attribute structure (TPMA_)
+
+TPM_RC_SIZE
+
+the value of a size parameter is larger or smaller than allowed
+
+TPM_RC_VALUE
+
+A parameter does not have one of its allowed values
+
+TPM_RC_TAG
+
+A parameter that should be a structure tag has a value that is not supported by
+the TPM
+
+In some commands, a parameter may not be used because of various options of that command.
+However, the unmarshaling code is required to validate that all parameters have values that are allowed
+by the Part 2 definition of the parameter type even if that parameter is not used in the command actions.
+
+Page 16
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+5
+
+Part 2: Structures
+
+Base Types
+
+5.1
+
+Primitive Types
+
+The types listed in Table 3 are the primitive types on which all of the other types and structures are
+based. The values in the “Type” column should be edited for the compiler and computer on which the
+TPM is implemented. The values in the “Name” column should remain the same because these values
+are used in the remainder of the specification.
+NOTE
+
+The types are compatible with the C99 standard and should be defined in stdint.h that is provided with a
+C99-compliant compiler;
+
+The parameters in the Name column should remain in the order shown.
+Table 3 — Definition of Base Types
+Type
+
+Name
+
+Description
+
+uint8_t
+
+UINT8
+
+unsigned, 8-bit integer
+
+uint8_t
+
+BYTE
+
+unsigned 8-bit integer
+
+int8_t
+
+INT8
+
+signed, 8-bit integer
+
+int
+
+BOOL
+
+a bit in an int
+This is not used across the interface but is used in many places in the code. If
+the type were sent on the interface, it would have to have a type with a specific
+number of bytes.
+
+uint16_t
+
+UINT16
+
+unsigned, 16-bit integer
+
+int16_t
+
+INT16
+
+signed, 16-bit integer
+
+uint32_t
+
+UINT32
+
+unsigned, 32-bit integer
+
+int32_t
+
+INT32
+
+signed, 32-bit integer
+
+uint64_t
+
+UINT64
+
+unsigned, 64-bit integer
+
+int64_t
+
+INT64
+
+signed, 64-bit integer
+
+5.2
+
+Miscellaneous Types
+
+These types are defined either for compatibility with previous versions of this specification or for clarity of
+this specification.
+Table 4 — Definition of Types for Documentation Clarity
+Type
+
+Name
+
+Description
+
+UINT32
+
+TPM_ALGORITHM_ID
+
+this is the 1.2 compatible form of the TPM_ALG_ID
+
+UINT32
+
+TPM_MODIFIER_INDICATOR
+
+UINT32
+
+TPM_AUTHORIZATION_SIZE
+
+the authorizationSize parameter in a command
+
+UINT32
+
+TPM_PARAMETER_SIZE
+
+the parameterSizeset parameter in a command
+
+UINT16
+
+TPM_KEY_SIZE
+
+a key size in octets
+
+UINT16
+
+TPM_KEY_BITS
+
+a key size in bits
+
+1.1.1.1.1
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 17
+October 31, 2013
+
+ Part 2: Structures
+
+6
+
+Trusted Platform Module Library
+
+Constants
+
+6.1
+
+TPM_SPEC (Specification Version Values)
+
+These values are readable with TPM2_GetCapability().
+NOTE
+
+This table will require editing when the specification is updated.
+
+Table 5 — Definition of (UINT32) TPM_SPEC Constants <>
+Name
+
+Value
+
+Comments
+ASCII “2.0” with null terminator
+
+TPM_SPEC_FAMILY
+
+0x322E3000
+
+TPM_SPEC_LEVEL
+
+00
+
+the level number for the specification
+
+TPM_SPEC_VERSION
+
+99
+
+the version number of the spec (00.99 * 100)
+
+TPM_SPEC_YEAR
+
+2013
+
+the year of the version
+
+TPM_SPEC_DAY_OF_YEAR
+
+304
+
+the day of the year (October 31, 2013)
+
+6.2
+
+TPM_GENERATED
+
+This constant value differentiates TPM-generated structures from non-TPM structures.
+Table 6 — Definition of (UINT32) TPM_GENERATED Constants <O>
+Name
+
+Value
+
+Comments
+
+TPM_GENERATED_VALUE
+
+0xff544347
+
+0xFF ‘TCG’ (FF 54 43 4716)
+
+Page 18
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.3
+
+Part 2: Structures
+
+TPM_ALG_ID
+
+The TCG maintains a registry of all algorithms that have an assigned algorithm ID. That registry is the
+definitive list of algorithms that may be supported by a TPM.
+NOTE
+
+Inclusion of an algorithm does NOT indicate that the necessary claims of the algorithm are av ailable
+under RAND terms from a TCG member.
+
+Table 7 is a copy of the TPM_ALG_ID constants table in the TCG registry as of the date of publication of
+this specification. Table 7 is provided for illustrative purposes only.
+{{Note for TCG Admin: Table 7 and the text in the paragraph above should be updated to reflect the final
+decisions by the TCG Board of Directors about inclusion of the table and the contents of the table. The
+desired approach is to leave the text as is and, immediately before publication of this specification for
+TCG admin to verify that Table 7 is the same as the algorithm registry table published by the TCG.}}
+An algorithm ID is often used like a tag to determine the type of a structure in a context-sensitive way.
+The values for TPM_ALG_ID shall be in the range of 00 0016 – 7F FF16. Other structure tags will be in the
+range 80 0016 – FF FF16.
+NOTE
+
+In TPM 1.2, these were defined as 32-bit constants. This specification limits the future size of the
+algorithm ID to 16 bits. The TPM_ALGORITHM_ID data type will continue to be a 32-bit number.
+
+An algorithm shall not be assigned a value in the range 00 C116 – 00 C616 in order to prevent any overlap
+with the command structure tags used in TPM 1.2.
+The implementation of some algorithms is dependent on the presence of other algorithms. When there is
+a dependency, the algorithm that is required is listed in column labeled "D" (dependent) in Table 7.
+EXAMPLE
+
+Implementation of TPM_ALG_RSASSA requires that the RSA algorithm be implemented.
+
+TPM_ALG_KEYEDHASH and TPM_ALG_NULL are required of all TPM implementations.
+Table 7 — Definition of (UINT16) TPM_ALG_ID Constants <IN/OUT, S>
+Algorithm Name
+
+Value
+
+Type
+
+a
+
+D
+
+Comments
+
+TPM_ALG_ERROR
+
+0x0000
+
+should not occur
+
+TPM_ALG_FIRST
+
+0x0001
+
+TPM_ALG_RSA
+
+0x0001
+
+AO
+
+the RSA algorithm
+
+TPM_ALG_SHA
+
+0x0004
+
+H
+
+the SHA1 algorithm
+
+TPM_ALG_SHA1
+
+0x0004
+
+H
+
+redefinition for documentation consistency
+OID 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 16
+
+TPM_ALG_HMAC
+
+0x0005
+
+HX
+
+the RFC 2104 Hash Message Authentication Code
+(HMAC) algorithm
+
+TPM_ALG_AES
+
+0x0006
+
+S
+
+
+TPM_ALG_MGF1
+
+0x0007
+
+HM
+
+the mask-generation function defined in IEEE Std
+1363-2000
+
+TPM_ALG_KEYEDHASH
+
+0x0008
+
+HEXO
+
+an encryption or signing algorithm using a keyed hash,
+defined by TCG in the TPM 2.0 specification
+may also refer to a data object that is neither signing
+nor encrypting
+
+TPM_ALG_XOR
+
+0x000A
+
+HS
+
+marker value
+
+the XOR obfuscation algorithm
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 19
+October 31, 2013
+
+ Part 2: Structures
+Algorithm Name
+
+Trusted Platform Module Library
+a
+
+Value
+
+Type
+
+TPM_ALG_SHA256
+
+0x000B
+
+H
+
+D
+
+Comments
+the SHA 256 algorithm
+OID 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05
+00 04 2016
+
+TPM_ALG_SHA384
+
+0x000C
+
+H
+
+the SHA 384 algorithm
+OID 30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05
+00 04 3016
+
+TPM_ALG_SHA512
+
+0x000D
+
+H
+
+the SHA 512 algorithm
+OID 30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05
+00 04 4016
+
+TPM_ALG_NULL
+
+0x0010
+
+TPM_ALG_SM3_256
+
+0x0012
+
+H
+
+hash algorithm standardized by OSCCA
+Block size is 512 bits.
+Output size is 256 bits.
+
+TPM_ALG_SM4
+
+0x0013
+
+S
+
+symmetric algorithm standardized by OSCCA
+Key and block size are 128 bits.
+
+TPM_ALG_RSASSA
+
+0x0014
+
+AX
+
+RSA a signature algorithm according to PKCS#1v2.1, 8.2
+
+TPM_ALG_RSAES
+
+0x0015
+
+AE
+
+RSA a padding algorithm according to PKCS#1v2.1, 7.2
+
+TPM_ALG_RSAPSS
+
+0x0016
+
+AX
+
+RSA signature algorithm (RSSASSA-PSS) according to
+PKCS#1v2.1, 8.1
+
+TPM_ALG_OAEP
+
+0x0017
+
+AE
+
+RSA padding algorithm
+PKCS#1v2.1, 7.1
+
+TPM_ALG_ECDSA
+
+0x0018
+
+AX
+
+ECC signature algorithm using elliptic curve cryptography
+(ECC)
+
+TPM_ALG_ECDH
+
+0x0019
+
+AM
+
+ECC secret sharing using ECC from SP800-56A
+Based on context, this can be either One-Pass DiffieHellman, C(1, 1, ECC CDH) defined in 6.2.2.2 or Full
+Unified Model C(2, 2, ECC CDH) defined in 6.1.1.2
+
+TPM_ALG_ECDAA
+
+0x001A
+
+AX
+
+ECC elliptic-curve based, anonymous signing scheme
+
+TPM_ALG_SM2
+
+0x001B
+
+AXE
+
+Null algorithm
+
+(RSAES_OAEP)
+
+according
+
+to
+
+ECC depending on context, either an elliptic-curve based,
+signature algorithm or a key exchange protocol
+NOTE
+
+This would be one of the algorithms specified in
+CM/T 0002 – 2012.
+
+TPM_ALG_ECSCHNORR
+
+0x001C
+
+AX
+
+ECC elliptic-curve-based Schnorr signature
+
+TPM_ALG_ECMQV
+
+0x001D
+
+AE
+
+ECC two-phase elliptic-curve key exchange -- C(2, 2, ECC
+MQV) from SP800-56A
+
+TPM_ALG_KDF1_SP800_56a
+
+0x0020
+
+HM
+
+ECC key derivation alternative #1 from SP800-56A
+
+TPM_ALG_KDF2
+
+0x0021
+
+HM
+
+key derivation function from IEEE Std 1363a-2004
+
+TPM_ALG_KDF1_SP800_108
+
+0x0022
+
+HM
+
+a key derivation method according to SP 800-108, "5.1
+KDF in Counter Mode”
+
+TPM_ALG_ECC
+
+0x0023
+
+AO
+
+prime field ECC
+
+TPM_ALG_SYMCIPHER
+
+0x0025
+
+O
+
+TPM_ALG_CTR
+
+0x0040
+
+SE
+
+Counter mode – if implemented, all symmetric block
+ciphers (S type) implemented shall be capable of using
+this mode.
+
+TPM_ALG_OFB
+
+0x0041
+
+SE
+
+Output Feedback mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+
+TPM_ALG_CBC
+
+0x0042
+
+SE
+
+Cipher Block Chaining mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+
+Page 20
+October 31, 2013
+
+the object type for a symmetric block cipher
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+a
+
+Algorithm Name
+
+Value
+
+Type
+
+TPM_ALG_CFB
+
+0x0043
+
+SE
+
+D
+
+Comments
+Cipher Feedback mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+
+TPM_ALG_ECB
+
+0x0044
+
+SE
+
+Electronic Codebook mode – if implemented, all
+symmetric block ciphers (S type) implemented shall be
+capable of using this mode.
+NOTE
+
+This mode is not recommended for uses unless
+the key is frequently rotated such as in video
+codecs.
+
+TPM_ALG_LAST
+
+0x0044
+
+marker value
+
+reserved
+
+0x00C1
+
+0x00C1 – 0x00C6 are reserved
+
+reserved
+
+0x00C2
+
+reserved
+
+0x00C3
+
+reserved
+
+0x00C4
+
+reserved
+
+0x00C5
+
+reserved
+
+0x00C6
+
+NOTE a Column Indicates the algorithm type and use of the algorithm inside of the TPM. The values are:
+A – asymmetric algorithm with a public and private key
+S – symmetric algorithm with only a private key
+H – hash algorithm that compresses input data to a digest value
+X – signing algorithm
+E – an encryption algorithm
+M – a method such as a mask generation function
+O – an object type
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 21
+October 31, 2013
+
+ Part 2: Structures
+6.4
+
+Trusted Platform Module Library
+
+TPM_ECC_CURVE
+
+The TCG maintains a registry of all curves that have an assigned curve identifier. That registry is the
+definitive list of curves that may be supported by a TPM.
+Table 8 is a copy of the TPM_ECC_CURVE constants table in the TCG registry as of the date of
+publication of this specification. Table 8 is provided for illustrative purposes only.
+{{Note for TCG Admin: Table 8 and the text in the paragraph above should be updated to reflect the final
+decisions by the TCG Board of Directors about inclusion of the table and the contents of the table. The
+desired approach is to leave the text as is and, immediately before publication of this specification for
+TCG admin to verify that Table 8 is the same as the curve registry table published by the TCG.}}
+Table 8 — Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants <IN/OUT, S>
+Name
+
+Value
+
+Comments
+
+TPM_ECC_NONE
+
+0x0000
+
+TPM_ECC_NIST_P192
+
+0x0001
+
+TPM_ECC_NIST_P224
+
+0x0002
+
+TPM_ECC_NIST_P256
+
+0x0003
+
+TPM_ECC_NIST_P384
+
+0x0004
+
+TPM_ECC_NIST_P521
+
+0x0005
+
+TPM_ECC_BN_P256
+
+0x0010
+
+curve to support ECDAA
+
+TPM_ECC_BN_P638
+
+0x0011
+
+curve to support ECDAA
+
+TPM_ECC_SM2_P256
+
+0x0020
+
+#TPM_RC_CURVE
+
+6.5
+6.5.1
+
+TPM_CC (Command Codes)
+Format
+
+A command is a 32-bit structure with fields assigned as shown in Figure 1.
+3 3 2 2
+1 0 9 8
+
+Res V
+
+1 1
+6 5
+
+Reserved
+
+0
+0
+
+Command Index
+
+Figure 1 — Command Format
+Table 9 — TPM Command Format Fields Description
+Bit
+15:0
+
+Name
+
+Definition
+
+Command Index
+
+the index of the command
+
+28:16 Reserved
+29
+
+V
+
+31:30 Res
+
+Page 22
+October 31, 2013
+
+shall be zero
+SET(1): the command is vendor specific
+CLEAR(0): the command is not vendor specific
+shall be zero
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.5.2
+
+Part 2: Structures
+
+Description
+
+Table 10 provides the legend for the interpretation of the column data in Table 11.
+Table 10 — Legend for Command Code Tables
+Column
+
+Allowed
+Values
+
+Comments
+
+Name
+
+Command
+Code Name
+
+Name of the command
+
+Command Code
+
+Numeric value
+
+the numeric value for the commandCode
+
+NV Write
+
+blank, Y, O
+
+indicates whether the command may cause an NV write operation
+If this column contains a “Y,” then successful completion of the
+command is expected to cause modification of the NV memory
+because of the command actions.
+If the column contains an “O,” then the command may cause a
+modification to NV associated with an orderly shutdown. That is, the
+command may modify the orderly save state of NV, in which case, an
+NV write will be necessary.
+NOTE 1
+
+Any command may be delayed in order for the TPM to complete
+NV actions due to a previous command or because of an
+asynchronous update of Clock.
+
+NOTE 2
+
+Any command with an authorization value may cause an NV write
+on an authorization failure but the command does not complete
+successfully.
+
+If the entry is blank, then writing to NV is not allowed in the command
+actions.
+Physical Presence
+
+blank, Y
+
+indicates whether the platformAuth for this command may require
+confirmation through a physical presence indication
+
+Encrypted
+
+blank, 2, 4
+
+A numeric value that indicates the number of octets in the size field of
+the first parameter of a command
+Blank indicates that no size field is present and no parameter
+encryption is allowed.
+
+Encrypt
+
+blank, 2, 4
+
+A numeric value that indicates the number of octets in the size field of
+the first parameter of a response
+Blank indicates that no size field is present and no parameter
+encryption is allowed.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 23
+October 31, 2013
+
+ Part 2: Structures
+6.5.3
+
+Trusted Platform Module Library
+
+TPM_CC Listing
+
+Table 11 lists the command codes and their attributes. The only normative column in this table is the
+column indicating the command code assigned to a specific command (the "Command Code" column).
+For all other columns, the command and response tables in Part 3 are definitive.
+
+Encrypt
+
+Encrypted
+
+Physical Presence
+
+NV Write
+
+Table 11 — Definition of (UINT32) TPM_CC Constants (Numeric Order) <IN/OUT, S>
+
+Name
+
+Command
+Code
+
+TPM_CC_FIRST
+
+0x0000011F
+
+Compile variable. May decrease
+based on implementation.
+
+TPM_CC_PP_FIRST
+
+0x0000011F
+
+Compile variable. Would decrease
+if new PP commands are added
+
+TPM_CC_NV_UndefineSpaceSpecial
+
+0x0000011F
+
+Y
+
+Y
+
+TPM_CC_EvictControl
+
+0x00000120
+
+Y
+
+Y
+
+TPM_CC_HierarchyControl
+
+0x00000121
+
+Y
+
+Y
+
+TPM_CC_NV_UndefineSpace
+
+0x00000122
+
+Y
+
+Y
+
+TPM_CC_ChangeEPS
+
+0x00000124
+
+Y
+
+Y
+
+TPM_CC_ChangePPS
+
+0x00000125
+
+Y
+
+Y
+
+TPM_CC_Clear
+
+0x00000126
+
+Y
+
+Y
+
+TPM_CC_ClearControl
+
+0x00000127
+
+Y
+
+Y
+
+TPM_CC_ClockSet
+
+0x00000128
+
+Y
+
+Y
+
+TPM_CC_HierarchyChangeAuth
+
+0x00000129
+
+Y
+
+Y
+
+2
+
+TPM_CC_NV_DefineSpace
+
+0x0000012A
+
+Y
+
+Y
+
+2
+
+TPM_CC_PCR_Allocate
+
+0x0000012B
+
+Y
+
+Y
+
+TPM_CC_PCR_SetAuthPolicy
+
+0x0000012C
+
+Y
+
+Y
+
+TPM_CC_PP_Commands
+
+0x0000012D
+
+Y
+
+Y
+
+TPM_CC_SetPrimaryPolicy
+
+0x0000012E
+
+Y
+
+Y
+
+2
+
+TPM_CC_FieldUpgradeStart
+
+0x0000012F
+
+O
+
+Y
+
+2
+
+TPM_CC_ClockRateAdjust
+
+0x00000130
+
+O
+
+Y
+
+TPM_CC_CreatePrimary
+
+0x00000131
+
+TPM_CC_NV_GlobalWriteLock
+
+0x00000132
+
+TPM_CC_PP_LAST
+
+0x00000132
+
+TPM_CC_GetCommandAuditDigest
+
+0x00000133
+
+Y
+
+TPM_CC_NV_Increment
+
+0x00000134
+
+Y
+
+Page 24
+October 31, 2013
+
+Y
+O
+
+Comments
+
+2
+
+2
+
+2
+
+Y
+Compile variable
+2
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Command
+Code
+
+TPM_CC_NV_SetBits
+
+0x00000135
+
+Y
+
+TPM_CC_NV_Extend
+
+0x00000136
+
+Y
+
+TPM_CC_NV_Write
+
+0x00000137
+
+Y
+
+TPM_CC_NV_WriteLock
+
+0x00000138
+
+Y
+
+TPM_CC_DictionaryAttackLockReset
+
+0x00000139
+
+O
+
+TPM_CC_DictionaryAttackParameters
+
+0x0000013A
+
+Y
+
+TPM_CC_NV_ChangeAuth
+
+0x0000013B
+
+Y
+
+2
+
+TPM_CC_PCR_Event
+
+0x0000013C
+
+O
+
+2
+
+TPM_CC_PCR_Reset
+
+0x0000013D
+
+O
+
+TPM_CC_SequenceComplete
+
+0x0000013E
+
+O
+
+TPM_CC_SetAlgorithmSet
+
+0x0000013F
+
+Y
+
+TPM_CC_SetCommandCodeAuditStatus
+
+0x00000140
+
+Y
+
+TPM_CC_FieldUpgradeData
+
+0x00000141
+
+O
+
+TPM_CC_IncrementalSelfTest
+
+0x00000142
+
+O
+
+TPM_CC_SelfTest
+
+0x00000143
+
+O
+
+TPM_CC_Startup
+
+0x00000144
+
+Y
+
+TPM_CC_Shutdown
+
+0x00000145
+
+Y
+
+TPM_CC_StirRandom
+
+0x00000146
+
+Y
+
+TPM_CC_ActivateCredential
+
+0x00000147
+
+TPM_CC_Certify
+
+0x00000148
+
+TPM_CC_PolicyNV
+
+0x00000149
+
+TPM_CC_CertifyCreation
+
+0x0000014A
+
+TPM_CC_Duplicate
+
+0x0000014B
+
+TPM_CC_GetTime
+
+0x0000014C
+
+O
+
+2
+
+TPM_CC_GetSessionAuditDigest
+
+0x0000014D
+
+O
+
+2
+
+TPM_CC_NV_Read
+
+0x0000014E
+
+TPM_CC_NV_ReadLock
+
+0x0000014F
+
+TPM_CC_ObjectChangeAuth
+
+0x00000150
+
+2
+
+TPM_CC_PolicySecret
+
+0x00000151
+
+2
+
+TPM_CC_Rewrap
+
+0x00000152
+
+2
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Encrypt
+
+Name
+
+NV Write
+
+Encrypted
+
+Part 2: Structures
+
+Physical Presence
+
+Trusted Platform Module Library
+
+2
+
+PCR
+PCR
+
+2
+
+2
+
+2
+
+2
+2
+
+O
+
+2
+
+2
+
+2
+
+2
+O
+
+Comments
+
+Policy
+
+2
+
+2
+
+2
+
+2
+
+2
+O
+
+Published
+Copyright © TCG 2006-2013
+
+2
+Policy
+2
+
+Page 25
+October 31, 2013
+
+ Trusted Platform Module Library
+
+Command
+Code
+
+Encrypt
+
+TPM_CC_Create
+
+0x00000153
+
+2
+
+2
+
+TPM_CC_ECDH_ZGen
+
+0x00000154
+
+2
+
+2
+
+TPM_CC_HMAC
+
+0x00000155
+
+2
+
+2
+
+TPM_CC_Import
+
+0x00000156
+
+2
+
+2
+
+TPM_CC_Load
+
+0x00000157
+
+2
+
+2
+
+TPM_CC_Quote
+
+0x00000158
+
+2
+
+2
+
+TPM_CC_RSA_Decrypt
+
+0x00000159
+
+TPM_CC_HMAC_Start
+
+0x0000015B
+
+2
+
+TPM_CC_SequenceUpdate
+
+0x0000015C
+
+2
+
+TPM_CC_Sign
+
+0x0000015D
+
+2
+
+TPM_CC_Unseal
+
+0x0000015E
+
+TPM_CC_PolicySigned
+
+0x00000160
+
+TPM_CC_ContextLoad
+
+0x00000161
+
+O
+
+Context
+
+TPM_CC_ContextSave
+
+0x00000162
+
+O
+
+Context
+
+TPM_CC_ECDH_KeyGen
+
+0x00000163
+
+2
+
+TPM_CC_EncryptDecrypt
+
+0x00000164
+
+2
+
+TPM_CC_FlushContext
+
+0x00000165
+
+TPM_CC_LoadExternal
+
+0x00000167
+
+2
+
+2
+
+TPM_CC_MakeCredential
+
+0x00000168
+
+2
+
+2
+
+TPM_CC_NV_ReadPublic
+
+0x00000169
+
+TPM_CC_PolicyAuthorize
+
+0x0000016A
+
+TPM_CC_PolicyAuthValue
+
+0x0000016B
+
+Policy
+
+TPM_CC_PolicyCommandCode
+
+0x0000016C
+
+Policy
+
+TPM_CC_PolicyCounterTimer
+
+0x0000016D
+
+2
+
+Policy
+
+TPM_CC_PolicyCpHash
+
+0x0000016E
+
+2
+
+Policy
+
+TPM_CC_PolicyLocality
+
+0x0000016F
+
+TPM_CC_PolicyNameHash
+
+0x00000170
+
+TPM_CC_PolicyOR
+
+0x00000171
+
+TPM_CC_PolicyTicket
+
+0x00000172
+
+TPM_CC_ReadPublic
+
+0x00000173
+
+Page 26
+October 31, 2013
+
+NV Write
+
+Name
+
+Encrypted
+
+Physical Presence
+
+Part 2: Structures
+
+O
+
+Comments
+
+2
+2
+
+2
+2
+
+Policy
+
+O
+
+Context
+
+NV
+2
+
+Policy
+
+Policy
+2
+
+Policy
+Policy
+
+2
+
+Published
+Copyright © TCG 2006-2013
+
+Policy
+2
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Encrypt
+
+2
+
+NV Write
+
+Encrypted
+
+Part 2: Structures
+
+Physical Presence
+
+Trusted Platform Module Library
+
+2
+
+2
+
+2
+
+Name
+
+Command
+Code
+
+TPM_CC_RSA_Encrypt
+
+0x00000174
+
+TPM_CC_StartAuthSession
+
+0x00000176
+
+TPM_CC_VerifySignature
+
+0x00000177
+
+TPM_CC_ECC_Parameters
+
+0x00000178
+
+TPM_CC_FirmwareRead
+
+0x00000179
+
+TPM_CC_GetCapability
+
+0x0000017A
+
+TPM_CC_GetRandom
+
+0x0000017B
+
+TPM_CC_GetTestResult
+
+0x0000017C
+
+TPM_CC_Hash
+
+0x0000017D
+
+TPM_CC_PCR_Read
+
+0x0000017E
+
+PCR
+
+TPM_CC_PolicyPCR
+
+0x0000017F
+
+Policy
+
+TPM_CC_PolicyRestart
+
+0x00000180
+
+TPM_CC_ReadClock
+
+0x00000181
+
+TPM_CC_PCR_Extend
+
+0x00000182
+
+O
+
+2
+
+TPM_CC_PCR_SetAuthValue
+
+0x00000183
+
+N
+
+2
+
+TPM_CC_NV_Certify
+
+0x00000184
+
+O
+
+TPM_CC_EventSequenceComplete
+
+0x00000185
+
+O
+
+TPM_CC_HashSequenceStart
+
+0x00000186
+
+TPM_CC_PolicyPhysicalPresence
+
+0x00000187
+
+Policy
+
+TPM_CC_PolicyDuplicationSelect
+
+0x00000188
+
+Policy
+
+TPM_CC_PolicyGetDigest
+
+0x00000189
+
+Policy
+
+TPM_CC_TestParms
+
+0x0000018A
+
+TPM_CC_Commit
+
+0x0000018B
+
+TPM_CC_PolicyPassword
+
+0x0000018C
+
+TPM_CC_ZGen_2Phase
+
+0x0000018D
+
+TPM_CC_EC_Ephemeral
+
+0x0000018E
+
+TPM_CC_PolicyNvWritten
+
+0x0000018F
+
+Policy
+
+TPM_CC_LAST
+
+0x0000018F
+
+Compile variable. May increase
+based on implementation.
+
+O
+
+Comments
+
+2
+
+2
+
+2
+
+O
+
+2
+
+2
+
+2
+Policy
+
+2
+
+2
+
+NOTE
+
+#TPM_RC_COMMAND_CODE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+This is not a FMT1 code
+and a parameter indicator
+value may not be added to
+
+Page 27
+October 31, 2013
+
+ Encrypt
+
+Encrypted
+
+Command
+Code
+
+Name
+
+Physical Presence
+
+Trusted Platform Module Library
+
+NV Write
+
+Part 2: Structures
+
+Comments
+this value.
+
+6.6
+
+TPM_RC (Response Codes)
+
+6.6.1
+
+Description
+
+Each return from the TPM has a 32-bit response code. The TPM will always set the upper 20 bits (31:12)
+of the response code to 0 00 0016 and the low-order 12 bits (11:00) will contain the response code.
+When a command succeeds, the TPM shall return TPM_RC_SUCCESS (0 0016) and will update any
+authorization-session nonce associated with the command.
+When a command fails to complete for any reason, the TPM shall return
+
+
+a TPM_ST (UINT16) with a value of TPM_TAG_RSP_COMMAND or TPM_ST_NO_SESSIONS,
+followed by
+
+
+
+a UINT32 (responseSize) with a value of 10, followed by
+
+
+
+a UINT32 containing a response code with a value other than TPM_RC_SUCCESS.
+
+Commands defined in this specification will use a tag of either TPM_ST_NO_SESSIONS or
+TPM_ST_SESSIONS. Error responses will use a tag value of TPM_ST_NO_SESSIONS and the
+response code will be as defined in this specification. Commands that use tags defined in the TPM 1.2
+specification will use TPM_TAG_RSP_COMMAND in an error and a response code defined in TPM 1.2.
+If the tag of the command is not a recognized command tag, the TPM error response will differ depending
+on TPM 1.2 compatibility. If the TPM supports 1.2 compatibility, the TPM shall return a tag of
+TPM_TAG_RSP_COMMAND and an appropriate TPM 1.2 response code (TPM_BADTAG =
+00 00 00 1E16). If the TPM does not have compatibility with TPM 1.2, the TPM shall return
+TPM_ST_NO_SESSION and a response code of TPM_RC_TAG.
+When a command fails, the TPM shall not update the authorization-session nonces associated with the
+command and will not close the authorization sessions used by the command. Audit digests will not be
+updated on an error. Unless noted in the command actions, a command that returns an error shall leave
+the state of the TPM as if the command had not been attempted. The exception to this principle is that a
+failure due to an authorization failure may update the dictionary-attack protection values.
+
+Page 28
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.6.2
+
+Part 2: Structures
+
+Response Code Formats
+
+The response codes for this specification are defined such that there is no overlap between the response
+codes used for this specification and those assigned in previous TPM specifications.
+The formats defined in this clause only apply when the tag for the response is TPM_ST_NO_SESSIONS.
+The response codes use two different format groups. One group contains the TPM 1.2 compatible
+response codes and the response codes for this specification that are not related to command
+parameters. The second group contains the errors that may be associated with a command parameter,
+handle, or session.
+Figure 2 shows the format for the response codes when bit 7 is zero.
+1
+1
+
+1
+0
+
+0
+9
+
+0
+8
+
+0
+7
+
+S
+
+bit
+
+T
+
+r
+
+V
+
+0
+6
+
+0
+5
+
+F
+
+0
+4
+
+0
+3
+
+0
+2
+
+0
+1
+
+0
+0
+
+E
+
+Figure 2 — Format-Zero Response Codes
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 29
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+The field definitions are:
+Table 12 — Format-Zero Response Codes
+Bit
+
+Name
+
+Definition
+
+06:00
+
+E
+
+the error number
+The interpretation of this field is dependent on the setting of the G and S fields.
+
+07
+
+F
+
+format selector
+CLEAR when the format is as defined in this Table 12 or when the response code is
+TPM_RC_BAD_TAG.
+
+08
+
+V
+
+version
+SET (1): The error number is defined in this specification and is returned when the response tag
+is TPM_ST_NO_SESSIONS.
+CLEAR (0): The error number is defined by a previous TPM specification. The error number is
+returned when the response tag is TPM_TAG_RSP_COMMAND.
+NOTE
+
+09
+
+In any error number returned by a TPM, the F (bit 7) and V (bit 8) attributes shall be CLEAR
+when the response tag is TPM_TAG_RSP_COMMAND value used in TPM 1.2.
+
+Reserved shall be zero.
+
+10
+
+T
+
+TCG/Vendor indicator
+SET (1): The response code is defined by the TPM vendor.
+CLEAR (0): The response code is defined by the TCG (a value in this specification).
+NOTE
+
+11
+
+S
+
+This attribute does not indicate a vendor-specific code unless the F attribute (bit[07]) is CLEAR.
+
+severity
+SET (1): The response code is a warning and the command was not necessarily in error. This
+command indicates that the TPM is busy or that the resources of the TPM have to be adjusted in
+order to allow the command to execute.
+CLEAR (0): The response code indicates that the command had an error that would prevent it
+from running.
+
+When the format bit (bit 7) is SET, then the error occurred during the unmarshaling or validation of an
+input parameter to the TPM. Figure 3 shows the format for the response codes when bit 7 is one.
+bit
+
+1
+1
+
+1
+0
+
+0
+9
+
+N
+
+0
+8
+
+0
+7
+
+0
+6
+
+1
+
+0
+5
+
+P
+
+0
+4
+
+0
+3
+
+0
+2
+
+0
+1
+
+0
+0
+
+E
+
+Figure 3 — Format-One Response Codes
+There are 64 errors with this format. The errors can be associated with a parameter, handle, or session.
+The error number for this format is in bits[05:00]. When an error is associated with a parameter, 0 40 16 is
+added and N is set to the parameter number.
+For an error associated with a handle, a parameter number (1 to 7) is added to the N field. For an error
+associated with a session, a value of 8 plus the session number (1 to 7) is added to the N field. In other
+words, if P is clear, then a value of 0 to 7 in the N field will indicate a handle error, and a value of 8 – 15
+will indicate a session error.
+NOTE
+
+If an implementation is not able to designate the handle, session, or parameter in error, then P and N will
+be zero.
+
+Page 30
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+The field definitions are:
+Table 13 — Format-One Response Codes
+Bit
+
+Name Definition
+
+05:00
+
+E
+
+the error number
+The error number is independent of the other settings.
+
+06
+
+P
+
+SET (1): The error is associated with a parameter.
+CLEAR (0): The error is associated with a handle or a session.
+
+07
+
+F
+
+the response code format selector
+This field shall be SET for the format in this table.
+
+11:08
+
+N
+
+the number of the handle, session, or parameter in error
+If P is SET, then this field is the parameter in error. If P is CLEAR, then this field indicates the
+handle or session in error. Handles use values of N between 0000 2 and 01112. Sessions use
+values between 10002 and 11112.
+
+The groupings of response codes are determined by bits 08, 07, and 06 of the response code as
+summarized in Table 14.
+Table 14 — Response Code Groupings
+Bit
+0
+8
+
+0
+7
+
+0
+6
+
+Definition
+
+0
+
+0
+
+x
+
+a response code defined by TPM 1.2
+NOTE
+
+An “x” in a column indicates that this may be either 0 or 1 and not affect the grouping of the response
+code.
+
+1
+
+0
+
+x
+
+a response code defined by this specification with no handle, session, or parameter number modifier
+
+x
+
+1
+
+0
+
+a response code defined by this specification with either a handle or session number modifier
+
+x
+
+1
+
+1
+
+a response code defined by this specification with a parameter number modifier
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 31
+October 31, 2013
+
+ Part 2: Structures
+6.6.3
+
+Trusted Platform Module Library
+
+TPM_RC Values
+
+In general, response codes defined in Part 2 will be unmarshaling errors and will have the F (format) bit
+SET. Codes that are unique to Part 3 will have the F bit CLEAR but the V (version) attribute will be SET to
+indicate that it is a TPM 2.0 response code.
+NOTE
+
+The constant RC_VER1 is used to indicate that the V attribute is SET and the constant RC_ FMT1 is used
+to indicate that the F attribute is SET and that the return code is variable based on handle, session, and
+parameter modifiers.
+
+Table 15 — Definition of (UINT32) TPM_RC Constants (Actions) <OUT>
+Name
+
+Value
+
+Description
+
+TPM_RC_SUCCESS
+
+0x000
+
+TPM_RC_BAD_TAG
+
+0x01E
+
+defined for compatibility with TPM 1.2
+
+RC_VER1
+
+0x100
+
+set for all format 0 response codes
+
+TPM_RC_INITIALIZE
+
+RC_VER1 + 0x000
+
+TPM not initialized
+commands not being accepted because of a TPM
+failure
+
+TPM_RC_FAILURE
+
+RC_VER1 + 0x001
+
+NOTE
+
+TPM_RC_SEQUENCE
+
+RC_VER1 + 0x003
+
+improper use of a sequence handle
+
+TPM_RC_PRIVATE
+
+RC_VER1 + 0x00B
+
+TPM_RC_HMAC
+
+RC_VER1 + 0x019
+
+TPM_RC_DISABLED
+
+RC_VER1 + 0x020
+
+TPM_RC_EXCLUSIVE
+
+RC_VER1 + 0x021
+
+command failed because audit sequence required
+exclusivity
+
+TPM_RC_AUTH_TYPE
+
+RC_VER1 + 0x024
+
+authorization handle is not correct for command
+
+TPM_RC_AUTH_MISSING
+
+RC_VER1 + 0x025
+
+command requires an authorization session for
+handle and it is not present.
+
+TPM_RC_POLICY
+
+RC_VER1 + 0x026
+
+policy Failure In Math Operation or an invalid
+authPolicy value
+
+TPM_RC_PCR
+
+RC_VER1 + 0x027
+
+PCR check fail
+
+TPM_RC_PCR_CHANGED
+
+RC_VER1 + 0x028
+
+PCR have changed since checked.
+
+TPM_RC_UPGRADE
+
+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
+
+TPM_RC_TOO_MANY_CONTEXTS
+
+RC_VER1 + 0x02E
+
+context ID counter is at maximum.
+
+TPM_RC_AUTH_UNAVAILABLE
+
+RC_VER1 + 0x02F
+
+authValue or authPolicy is not available for
+selected entity.
+
+TPM_RC_REBOOT
+
+RC_VER1 + 0x030
+
+a _TPM_Init and Startup(CLEAR) is required
+before the TPM can resume operation.
+
+TPM_RC_UNBALANCED
+
+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.
+
+Page 32
+October 31, 2013
+
+This
+may
+be
+returned
+by
+TPM2_GetTestResult() as the testResult
+parameter.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Name
+
+Part 2: Structures
+Value
+
+Description
+
+TPM_RC_COMMAND_SIZE
+
+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
+
+TPM_RC_COMMAND_CODE
+
+RC_VER1 + 0x043
+
+command code not supported
+
+TPM_RC_AUTHSIZE
+
+RC_VER1 + 0x044
+
+the value of authorizationSize is out of range or the
+number of octets in the Authorization Area is
+greater than required
+
+TPM_RC_AUTH_CONTEXT
+
+RC_VER1 + 0x045
+
+use of an authorization session with a context
+command
+
+TPM_RC_NV_RANGE
+
+RC_VER1 + 0x046
+
+NV offset+size is out of range.
+
+TPM_RC_NV_SIZE
+
+RC_VER1 + 0x047
+
+Requested allocation size is larger than allowed.
+
+TPM_RC_NV_LOCKED
+
+RC_VER1 + 0x048
+
+NV access locked.
+
+TPM_RC_NV_AUTHORIZATION
+
+RC_VER1 + 0x049
+
+NV access authorization fails in command actions
+(this failure does not affect lockout.action)
+
+TPM_RC_NV_UNINITIALIZED
+
+RC_VER1 + 0x04A
+
+an NV Index is used before being initialized or the
+state saved by TPM2_Shutdown(STATE) could not
+be restored
+
+TPM_RC_NV_SPACE
+
+RC_VER1 + 0x04B
+
+insufficient space for NV allocation
+
+TPM_RC_NV_DEFINED
+
+RC_VER1 + 0x04C
+
+NV Index or persistend object already defined
+
+TPM_RC_BAD_CONTEXT
+
+RC_VER1 + 0x050
+
+context in TPM2_ContextLoad() is not valid
+
+TPM_RC_CPHASH
+
+RC_VER1 + 0x051
+
+cpHash value already set or not correct for use
+
+TPM_RC_PARENT
+
+RC_VER1 + 0x052
+
+handle for parent is not a valid parent
+
+TPM_RC_NEEDS_TEST
+
+RC_VER1 + 0x053
+
+some function needs testing.
+
+TPM_RC_NO_RESULT
+
+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.
+
+TPM_RC_SENSITIVE
+
+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
+
+RC_MAX_FM0
+
+RC_VER1 + 0x07F
+
+largest version 1 code that is not a warning
+
+New Subsection
+
+RC_FMT1
+
+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.
+
+TPM_RC_ASYMMETRIC
+
+RC_FMT1 + 0x001
+
+asymmetric algorithm not supported or not correct
+
+TPM_RC_ATTRIBUTES
+
+RC_FMT1 + 0x002
+
+inconsistent attributes
+
+TPM_RC_HASH
+
+RC_FMT1 + 0x003
+
+hash algrithm not supported or not appropriate
+
+TPM_RC_VALUE
+
+RC_FMT1 + 0x004
+
+value is out of range or is not correct for the
+context
+
+TPM_RC_HIERARCHY
+
+RC_FMT1 + 0x005
+
+hierarchy is not enabled or is not correct for the
+use
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 33
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Name
+
+Value
+
+Description
+
+TPM_RC_KEY_SIZE
+
+RC_FMT1 + 0x007
+
+key size is not supported
+
+TPM_RC_MGF
+
+RC_FMT1 + 0x008
+
+mask generation function not supported
+
+TPM_RC_MODE
+
+RC_FMT1 + 0x009
+
+mode of operation not supported
+
+TPM_RC_TYPE
+
+RC_FMT1 + 0x00A
+
+the type of the value is not appropriate for the use
+
+TPM_RC_HANDLE
+
+RC_FMT1 + 0x00B
+
+the handle is not correct for the use
+
+TPM_RC_KDF
+
+RC_FMT1 + 0x00C
+
+unsupported key derivation function or function not
+appropriate for use
+
+TPM_RC_RANGE
+
+RC_FMT1 + 0x00D
+
+value was out of allowed range.
+
+TPM_RC_AUTH_FAIL
+
+RC_FMT1 + 0x00E
+
+the authorization HMAC check failed and DA
+counter incremented
+
+TPM_RC_NONCE
+
+RC_FMT1 + 0x00F
+
+invalid nonce size
+
+TPM_RC_PP
+
+RC_FMT1 + 0x010
+
+authorization requires assertion of PP
+
+TPM_RC_SCHEME
+
+RC_FMT1 + 0x012
+
+unsupported or incompatible scheme
+
+TPM_RC_SIZE
+
+RC_FMT1 + 0x015
+
+structure is the wrong size
+
+TPM_RC_SYMMETRIC
+
+RC_FMT1 + 0x016
+
+unsupported symmetric algorithm or key size, or
+not appropriate for instance
+
+TPM_RC_TAG
+
+RC_FMT1 + 0x017
+
+incorrect structure tag
+
+TPM_RC_SELECTOR
+
+RC_FMT1 + 0x018
+
+union selector is incorrect
+
+TPM_RC_INSUFFICIENT
+
+RC_FMT1 + 0x01A
+
+the TPM was unable to unmarshal a value
+because there were not enough octets in the input
+buffer
+
+TPM_RC_SIGNATURE
+
+RC_FMT1 + 0x01B
+
+the signature is not valid
+
+TPM_RC_KEY
+
+RC_FMT1 + 0x01C
+
+key fields are not compatible with the selected use
+
+TPM_RC_POLICY_FAIL
+
+RC_FMT1 + 0x01D
+
+a policy check failed
+
+TPM_RC_INTEGRITY
+
+RC_FMT1 + 0x01F
+
+integrity check failed
+
+TPM_RC_TICKET
+
+RC_FMT1 + 0x020
+
+invalid ticket
+
+TPM_RC_RESERVED_BITS
+
+RC_FMT1 + 0x021
+
+reserved bits not set to zero as required
+
+TPM_RC_BAD_AUTH
+
+RC_FMT1 + 0x022
+
+authroization failure without DA implications
+
+TPM_RC_EXPIRED
+
+RC_FMT1 + 0x023
+
+the policy has expired
+
+TPM_RC_POLICY_CC
+
+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
+
+TPM_RC_BINDING
+
+RC_FMT1 + 0x025
+
+public and sensitive portions of an object are not
+cryptographically bound
+
+TPM_RC_CURVE
+
+RC_FMT1 + 0x026
+
+curve not supported
+
+TPM_RC_ECC_POINT
+
+RC_FMT1 + 0x027
+
+point is not on the required curve.
+
+New Subsection
+RC_WARN
+
+0x900
+
+set for warning response codes
+
+TPM_RC_CONTEXT_GAP
+
+RC_WARN + 0x001
+
+gap for context ID is too large
+
+TPM_RC_OBJECT_MEMORY
+
+RC_WARN + 0x002
+
+out of memory for object contexts
+
+Page 34
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Name
+
+Value
+
+Description
+
+TPM_RC_SESSION_MEMORY
+
+RC_WARN + 0x003
+
+out of memory for session contexts
+
+TPM_RC_MEMORY
+
+RC_WARN + 0x004
+
+out of shared object/session memory or need
+space for internal operations
+
+TPM_RC_SESSION_HANDLES
+
+RC_WARN + 0x005
+
+out of session handles – a session must be flushed
+before a new session may be created
+out of object handles – the handle space for
+objects is depleted and a reboot is required
+NOTE
+
+This cannot occur
+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.
+
+TPM_RC_OBJECT_HANDLES
+
+RC_WARN + 0x006
+
+TPM_RC_LOCALITY
+
+RC_WARN + 0x007
+
+TPM_RC_YIELDED
+
+RC_WARN + 0x008
+
+on
+
+the
+
+reference
+
+bad locality
+the TPM has suspended operation on the
+command; forward progress was made and the
+command may be retried.
+See Part 1, “Multi-tasking.”
+NOTE
+
+This cannot occur
+implementation.
+
+on
+
+the
+
+reference
+
+TPM_RC_CANCELED
+
+RC_WARN + 0x009
+
+the command was canceled
+
+TPM_RC_TESTING
+
+RC_WARN + 0x00A
+
+TPM is performing self-tests
+
+TPM_RC_REFERENCE_H0
+
+RC_WARN + 0x010
+
+the 1 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H1
+
+RC_WARN + 0x011
+
+the 2 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H2
+
+RC_WARN + 0x012
+
+the 3 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H3
+
+RC_WARN + 0x013
+
+the 4 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H4
+
+RC_WARN + 0x014
+
+the 5 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H5
+
+RC_WARN + 0x015
+
+the 6 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_H6
+
+RC_WARN + 0x016
+
+the 7 handle in the handle area references a
+transient object or session that is not loaded
+
+TPM_RC_REFERENCE_S0
+
+RC_WARN + 0x018
+
+the 1 authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S1
+
+RC_WARN + 0x019
+
+the 2 authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S2
+
+RC_WARN + 0x01A
+
+the 3 authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S3
+
+RC_WARN + 0x01B
+
+the 4th authorization session handle references a
+session that is not loaded
+
+TPM_RC_REFERENCE_S4
+
+RC_WARN + 0x01C
+
+the 5 session handle references a session that is
+not loaded
+
+TPM_RC_REFERENCE_S5
+
+RC_WARN + 0x01D
+
+the 6 session handle references a session that is
+not loaded
+
+st
+
+nd
+
+rd
+
+th
+
+th
+
+th
+
+th
+
+st
+
+nd
+
+rd
+
+th
+
+th
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 35
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Name
+
+Value
+
+Description
+
+TPM_RC_REFERENCE_S6
+
+RC_WARN + 0x01E
+
+the 7 authorization session handle references a
+session that is not loaded
+
+TPM_RC_NV_RATE
+
+RC_WARN + 0x020
+
+the TPM is rate-limiting accesses to prevent
+wearout of NV
+
+TPM_RC_LOCKOUT
+
+RC_WARN + 0x021
+
+authorizations for objects subject to DA protection
+are not allowed at this time because the TPM is in
+DA lockout mode
+
+TPM_RC_RETRY
+
+RC_WARN + 0x022
+
+the TPM was not able to start the command
+
+TPM_RC_NV_UNAVAILABLE
+
+RC_WARN + 0x023
+
+the command may require writing of NV and NV is
+not current accessible
+
+TPM_RC_NOT_USED
+
+RC_WARN + 0x7F
+
+this value is reserved and shall not be returned by
+the TPM
+
+th
+
+Additional Defines
+TPM_RC_H
+
+0x000
+
+add to a handle-related error
+
+TPM_RC_P
+
+0x040
+
+add to a parameter-related error
+
+TPM_RC_S
+
+0x800
+
+add to a session-related error
+
+TPM_RC_1
+
+0x100
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_2
+
+0x200
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_3
+
+0x300
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_4
+
+0x400
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_5
+
+0x500
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_6
+
+0x600
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_7
+
+0x700
+
+add to a parameter-, handle-, or session-related
+error
+
+TPM_RC_8
+
+0x800
+
+add to a parameter-related error
+
+TPM_RC_9
+
+0x900
+
+add to a parameter-related error
+
+TPM_RC_A
+
+0xA00
+
+add to a parameter-related error
+
+TPM_RC_B
+
+0xB00
+
+add to a parameter-related error
+
+TPM_RC_C
+
+0xC00
+
+add to a parameter-related error
+
+TPM_RC_D
+
+0xD00
+
+add to a parameter-related error
+
+TPM_RC_E
+
+0xE00
+
+add to a parameter-related error
+
+TPM_RC_F
+
+0xF00
+
+add to a parameter-related error
+
+TPM_RC_N_MASK
+
+0xF00
+
+number mask
+
+Page 36
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+6.7
+
+Part 2: Structures
+
+TPM_CLOCK_ADJUST
+
+A TPM_CLOCK_ADJUST value is used to change the rate at which the TPM internal oscillator is divided.
+A change to the divider will change the rate at which Clock and Time change.
+NOTE
+
+The recommended adjustments are approximately 1% for a course adjustment, 0.1% for a medium
+adjustment, and the minimum possible on the implementation for the fine adjustment (e.g., one count of
+the pre-scalar if possible).
+
+Table 16 — Definition of (INT8) TPM_CLOCK_ADJUST Constants <IN>
+Name
+
+Value
+
+Comments
+
+TPM_CLOCK_COARSE_SLOWER
+
+-3
+
+Slow the Clock update rate by one coarse adjustment step.
+
+TPM_CLOCK_MEDIUM_SLOWER
+
+-2
+
+Slow the Clock update rate by one medium adjustment step.
+
+TPM_CLOCK_FINE_SLOWER
+
+-1
+
+Slow the Clock update rate by one fine adjustment step.
+
+TPM_CLOCK_NO_CHANGE
+
+0
+
+No change to the Clock update rate.
+
+TPM_CLOCK_FINE_FASTER
+
+1
+
+Speed the Clock update rate by one fine adjustment step.
+
+TPM_CLOCK_MEDIUM_FASTER
+
+2
+
+Speed the Clock update rate by one medium adjustment step.
+
+TPM_CLOCK_COARSE_FASTER
+
+3
+
+Speed the Clock update rate by one coarse adjustment step.
+
+#TPM_RC_VALUE
+
+6.8
+
+TPM_EO (EA Arithmetic Operands)
+Table 17 — Definition of (UINT16) TPM_EO Constants <IN/OUT>
+
+Operation Name
+
+Value
+
+Comments
+
+TPM_EO_EQ
+
+0x0000
+
+A=B
+
+TPM_EO_NEQ
+
+0x0001
+
+A≠B
+
+TPM_EO_SIGNED_GT
+
+0x0002
+
+A > B signed
+
+TPM_EO_UNSIGNED_GT
+
+0x0003
+
+A > B unsigned
+
+TPM_EO_SIGNED_LT
+
+0x0004
+
+A < B signed
+
+TPM_EO_UNSIGNED_LT
+
+0x0005
+
+A < B unsigned
+
+TPM_EO_SIGNED_GE
+
+0x0006
+
+A ≥ B signed
+
+TPM_EO_UNSIGNED_GE
+
+0x0007
+
+A ≥ B unsigned
+
+TPM_EO_SIGNED_LE
+
+0x0008
+
+A ≤ B signed
+
+TPM_EO_UNSIGNED_LE
+
+0x0009
+
+A ≤ B unsigned
+
+TPM_EO_BITSET
+
+0x000A
+
+All bits SET in B are SET in A. ((A&B)=B)
+
+TPM_EO_BITCLEAR
+
+0x000B
+
+All bits SET in B are CLEAR in A. ((A&B)=0)
+
+#TPM_RC_VALUE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Response code returned when unmarshaling of this type fails
+
+Published
+Copyright © TCG 2006-2013
+
+Page 37
+October 31, 2013
+
+ Part 2: Structures
+
+6.9
+
+Trusted Platform Module Library
+
+TPM_ST (Structure Tags)
+
+Structure tags are used to disambiguate structures. They are 16-bit values with the most significant bit
+SET so that they do not overlap TPM_ALG_ID values. A single exception is made for the value
+associated with TPM_ST_RSP_COMMAND (0x00C4), which has the same value as the
+TPM_TAG_RSP_COMMAND tag from earlier versions of this specification. This value is used when the
+TPM is compatible with a previous TPM specification and the TPM cannot determine which family of
+response code to return because the command tag is not valid.
+Many of the structures defined in this document have parameters that are unions of other structures. That
+is, a parameter may be one of several structures. The parameter will have a selector value that indicates
+which of the options is actually present.
+In order to allow the marshaling and unmarshaling code to determine which of the possible structures is
+allowed, each selector will have a unique interface type and will constrain the number of possible tag
+values.
+Table 18 defines the structure tags values. The definition of many structures is context-sensitive using an
+algorithm ID. In cases where an algorithm ID is not a meaningful way to designate the structure, the
+values in this table are used.
+Table 18 — Definition of (UINT16) TPM_ST Constants <IN/OUT, S>
+Name
+TPM_ST_RSP_COMMAND
+
+Value
+
+Comments
+
+0x00C4
+
+
+TPM_ST_NULL
+
+0X8000
+
+no structure type specified
+
+TPM_ST_NO_SESSIONS
+
+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
+authorizationSize/parameterSize value is present
+If the responseCode from the TPM is not
+TPM_RC_SUCCESS, then the response tag shall
+have this value.
+
+TPM_ST_SESSIONS
+
+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 authorizationSize/parameterSize
+field is present
+
+Page 38
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Name
+reserved
+
+Part 2: Structures
+Value
+
+Comments
+
+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 TPM_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
+
+reserved
+
+0x8004
+
+This tag is not used by all TPM or TRM
+implementations.
+
+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 TPM_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.
+
+TPM_ST_ATTEST_NV
+
+0x8014
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_COMMAND_AUDIT
+
+0x8015
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_SESSION_AUDIT
+
+0x8016
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_CERTIFY
+
+0x8017
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_QUOTE
+
+0x8018
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_TIME
+
+0x8019
+
+tag for an attestation structure
+
+TPM_ST_ATTEST_CREATION
+
+0x801A
+
+tag for an attestation structure
+
+reserved
+
+0x801B
+
+do not use
+NOTE
+
+This
+was
+previously
+assigned
+to
+TPM_ST_ATTEST_NV. The tag is changed
+because the structure has changed
+
+TPM_ST_CREATION
+
+0x8021
+
+tag for a ticket type
+
+TPM_ST_VERIFIED
+
+0x8022
+
+tag for a ticket type
+
+TPM_ST_AUTH_SECRET
+
+0x8023
+
+tag for a ticket type
+
+TPM_ST_HASHCHECK
+
+0x8024
+
+tag for a ticket type
+
+TPM_ST_AUTH_SIGNED
+
+0x8025
+
+tag for a ticket type
+
+TPM_ST_FU_MANIFEST
+
+0x8029
+
+tag for a structure describing a Field Upgrade Policy
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 39
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+6.10 TPM_SU (Startup Type)
+These values are used in TPM2_Startup() to indicate the shutdown and startup mode. The defined
+startup sequences are:
+a) TPM Reset – Two cases:
+1) Shutdown(CLEAR) followed by Startup(CLEAR)
+2) Startup(CLEAR) with no Shutdown()
+b) TPM Restart – Shutdown(STATE) followed by Startup(CLEAR)
+c) TPM Resume – Shutdown(STATE) followed by Startup(STATE)
+TPM_SU values of 80 0016 and above are reserved for internal use of the TPM and may not be assigned
+values.
+NOTE
+
+In the reference code, a value of FF FF 16 indicates that the startup state has not been set. If this was
+defined in this table to be, say, TPM_SU_NONE, then TPM_SU_NONE would be a valid input value but
+the caller is not allowed to indicate the that the startup type is TPM_SU_NONE so the reserved value is
+defined in the implementation as required for internal TPM uses.
+
+Table 19 — Definition of (UINT16) TPM_SU Constants <IN>
+Name
+
+Value
+
+Description
+
+TPM_SU_CLEAR
+
+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 start from
+perform TPM Reset or TPM Restart
+
+TPM_SU_STATE
+
+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(TPM_SU_STATE)
+
+#TPM_RC_VALUE
+
+response code when incorrect value is used
+
+6.11 TPM_SE (Session Type)
+This type is used in TPM2_StartAuthSession() to indicate the type of the session to be created.
+Table 20 — Definition of (UINT8) TPM_SE Constants <IN>
+Name
+
+Value
+
+TPM_SE_HMAC
+
+0x00
+
+TPM_SE_POLICY
+
+0x01
+
+TPM_SE_TRIAL
+
+0x03
+
+#TPM_RC_VALUE
+
+Page 40
+October 31, 2013
+
+Description
+
+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.
+response code when incorrect value is used
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+6.12 TPM_CAP (Capabilities)
+The TPM_CAP values are used in TPM2_GetCapability() to select the type of the value to be returned.
+The format of the response varies according to the type of the value.
+Table 21 — Definition of (UINT32) TPM_CAP Constants
+Capability Name
+
+Value
+
+Property Type
+
+Return Type
+
+TPM_CAP_FIRST
+
+0x00000000
+
+TPM_CAP_ALGS
+
+0x00000000
+
+TPM_CAP_HANDLES
+
+0x00000001
+
+TPML_HANDLE
+
+TPM_CAP_COMMANDS
+
+0x00000002
+
+TPML_CCA
+
+TPM_CAP_PP_COMMANDS
+
+0x00000003
+
+TPML_CC
+
+TPM_CAP_AUDIT_COMMANDS
+
+0x00000004
+
+TPML_CC
+
+TPM_CAP_PCRS
+
+0x00000005
+
+TPML_PCR_SELECTION
+
+TPM_CAP_TPM_PROPERTIES
+
+0x00000006
+
+TPML_TAGGED_TPM_PROPERTY
+
+TPM_CAP_PCR_PROPERTIES
+
+0x00000007
+
+(1)
+
+TPM_CAP_ECC_CURVES
+
+0x00000008
+
+TPML_ALG_PROPERTY
+
+TPML_TAGGED_PCR_PROPERTY
+(1)
+
+TPM_CAP_LAST
+
+0x00000008
+
+TPM_CAP_VENDOR_PROPERTY
+0x00000100
+
+TPML_ECC_CURVE
+
+manufacturer-specific values
+
+#TPM_RC_VALUE
+NOTES:
+(1) The TPM_ALG_ID or TPM_ECC_CURVE is cast to a UINT32
+
+6.13 TPM_PT (Property Tag)
+The TPM_PT constants are used in TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES) to
+indicate the property being selected or returned.
+The values in the fixed group (PT_FIXED) are not changeable through programmatic means other than a
+firmware update. The values in the variable group (PT_VAR) may be changed with TPM commands but
+should be persistent over power cycles and only changed when indicated by the detailed actions code.
+Table 22 — Definition of (UINT32) TPM_PT Constants <IN/OUT, S>
+Capability Name
+
+Value
+
+Comments
+
+TPM_PT_NONE
+
+0x00000000
+
+indicates no property type
+
+PT_GROUP
+
+0x00000100
+
+The number of properties in each group.
+NOTE The first group with any properties is group 1
+(PT_GROUP * 1). Group 0 is reserved.
+
+PT_FIXED
+
+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.
+
+TPM_PT_FAMILY_INDICATOR
+
+PT_FIXED + 0
+ a 4-octet character string containing the TPM Family value
+(TPM_SPEC_FAMILY)
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 41
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+TPM_PT_LEVEL
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+PT_FIXED + 1
+ the level of the specification
+NOTE 1
+
+TPM_PT_REVISION
+
+PT_FIXED + 2
+For this specification, the level is zero.
+
+NOTE 2
+
+The level is on the title page of the specification.
+
+ the specification Revision times 100
+EXAMPLE Revision 01.01 would have a value of 101.
+NOTE
+
+TPM_PT_DAY_OF_YEAR
+
+PT_FIXED + 3
+The Revision value is on the title page of the
+specification.
+
+ 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
+
+TPM_PT_YEAR
+
+PT_FIXED + 4
+The specification date is on the title page of the
+specification.
+
+ 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.
+
+TPM_PT_MANUFACTURER
+
+PT_FIXED + 5
+ the vendor ID unique to each TPM manufacturer
+
+TPM_PT_VENDOR_STRING_1
+
+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.
+
+TPM_PT_VENDOR_STRING_2
+
+PT_FIXED + 7
+ the second four characters of the vendor ID string
+
+TPM_PT_VENDOR_STRING_3
+
+PT_FIXED + 8
+ the third four characters of the vendor ID string
+
+TPM_PT_VENDOR_STRING_4
+
+PT_FIXED + 9
+ the fourth four characters of the vendor ID sting
+
+TPM_PT_VENDOR_TPM_TYPE
+
+PT_FIXED + 10
+ vendor-defined value indicating the TPM model
+
+TPM_PT_FIRMWARE_VERSION_1
+
+PT_FIXED + 11
+ the most-significant 32 bits of a vendor-specific value
+indicating the version of the firmware
+
+TPM_PT_FIRMWARE_VERSION_2
+
+PT_FIXED + 12
+ the least-significant 32 bits of a vendor-specific value
+indicating the version of the firmware
+
+TPM_PT_INPUT_BUFFER
+
+PT_FIXED + 13
+ the maximum size of
+TPM2B_MAX_BUFFER)
+
+TPM_PT_HR_TRANSIENT_MIN
+
+PT_FIXED + 14
+ the minimum number of transient objects that can be held
+in TPM RAM
+NOTE
+
+TPM_PT_HR_PERSISTENT_MIN
+
+PT_FIXED + 15
+parameter
+
+(typically,
+
+a
+
+This minimum shall be no less than the minimum
+value required by the platform-specific specification
+to which the TPM is built.
+
+ the minimum number of persistent objects that can be
+held in TPM NV memory
+NOTE
+
+TPM_PT_HR_LOADED_MIN
+
+PT_FIXED + 16
+a
+
+This minimum shall be no less than the minimum
+value required by the platform-specific specification
+to which the TPM is built.
+
+ the minimum number of authorization sessions that can
+be held in TPM RAM
+NOTE
+
+Page 42
+October 31, 2013
+
+This minimum shall be no less than the minimum
+value required by the platform-specific specification
+to which the TPM is built.
+
+Published
+
+Family “2.0”
+
+Copyright © TCG 2006-2013
+
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Capability Name
+TPM_PT_ACTIVE_SESSIONS_MAX
+
+Part 2: Structures
+Value
+
+Comments
+
+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.
+
+TPM_PT_PCR_COUNT
+
+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.
+
+TPM_PT_PCR_SELECT_MIN
+
+PT_FIXED + 19
+ the
+minimum
+number
+of
+TPMS_PCR_SELECT.sizeOfSelect
+NOTE
+
+TPM_PT_CONTEXT_GAP_MAX
+
+PT_FIXED + 20
+octets
+
+in
+
+a
+
+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.
+
+ the maximum allowed difference (unsigned) between the
+contextID values of two saved session contexts
+16
+
+This value shall be at least 2 -1 (65535).
+PT_FIXED + 21
+ skipped
+TPM_PT_NV_COUNTERS_MAX
+
+PT_FIXED + 22
+ the maximum number of NV Indexes that are allowed to
+have the TPMA_NV_COUNTER attribute SET
+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.
+
+TPM_PT_NV_INDEX_MAX
+
+PT_FIXED + 23
+ the maximum size of an NV Index data area
+
+TPM_PT_MEMORY
+
+PT_FIXED + 24
+ a TPMA_MEMORY indicating the memory management
+method for the TPM
+
+TPM_PT_CLOCK_UPDATE
+
+PT_FIXED + 25
+ interval, in milliseconds, between updates to the copy of
+TPMS_CLOCK_INFO.clock in NV
+
+TPM_PT_CONTEXT_HASH
+
+PT_FIXED + 26
+ the algorithm used for the integrity HMAC on saved
+contexts
+and
+for
+hashing
+the
+fuData
+of
+TPM2_FirmwareRead()
+
+TPM_PT_CONTEXT_SYM
+
+PT_FIXED + 27
+ the algorithm used for encryption of saved contexts
+
+TPM_PT_CONTEXT_SYM_SIZE
+
+PT_FIXED + 28
+ the size of the key used for encryption of saved contexts
+
+TPM_PT_ORDERLY_COUNT
+
+PT_FIXED + 29
+ the modulus - 1 of the count for NV update of an orderly
+counter
+The returned value is MAX_ORDERLY_COUNT.
+N
+This will have a value of 2 – 1 where 1 ≤ N ≤ 32
+NOTE
+
+An “orderly counter” is an NV Index with
+TPMA_NV_COUNTER and TPMA_NV_ORDERLY
+both SET.
+
+TPM_PT_MAX_COMMAND_SIZE
+
+PT_FIXED + 30
+ the maximum value for commandSize in a command
+
+TPM_PT_MAX_RESPONSE_SIZE
+
+PT_FIXED + 31
+ the maximum value for responseSize in a response
+
+TPM_PT_MAX_DIGEST
+
+PT_FIXED + 32
+ the maximum size of a digest that can be produced by the
+TPM
+
+TPM_PT_MAX_OBJECT_CONTEXT
+
+PT_FIXED + 33
+ the maximum size of an object context that will be
+returned by TPM2_ContextSave
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 43
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+TPM_PT_MAX_SESSION_CONTEXT
+PT_FIXED + 34
+ the maximum size of a session context that will be
+returned by TPM2_ContextSave
+TPM_PT_PS_FAMILY_INDICATOR
+
+PT_FIXED + 35
+ platform-specific family (a TPM_PS value)(see Table 24)
+NOTE
+
+The platform-specific values for the TPM_PT_PS
+parameters are in the relevant platform-specific
+specification. In the reference implementation, all of
+these values are 0.
+
+TPM_PT_PS_LEVEL
+
+PT_FIXED + 36
+ the level of the platform-specific specification
+
+TPM_PT_PS_REVISION
+
+PT_FIXED + 37
+ the specification Revision times 100 for the platformspecific specification
+
+TPM_PT_PS_DAY_OF_YEAR
+
+PT_FIXED + 38
+ the platform-specific specification day of year using TCG
+calendar
+
+TPM_PT_PS_YEAR
+
+PT_FIXED + 39
+ the platform-specific specification year using the CE
+
+TPM_PT_SPLIT_MAX
+
+PT_FIXED + 40
+ the number of split signing operations supported by the
+TPM
+
+TPM_PT_TOTAL_COMMANDS
+
+PT_FIXED + 41
+ total number of commands implemented in the TPM
+
+TPM_PT_LIBRARY_COMMANDS
+
+PT_FIXED + 42
+ number of commands from the TPM library that are
+implemented
+
+TPM_PT_VENDOR_COMMANDS
+
+PT_FIXED + 43
+ number of vendor commands that are implemented
+
+TPM_PT_NV_BUFFER_MAX
+
+PT_FIXED + 44
+ the maximum data size in one NV write command
+
+PT_VAR
+
+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.
+
+TPM_PT_PERMANENT
+
+PT_VAR + 0
+
+TPMA_PERMANENT
+
+TPM_PT_STARTUP_CLEAR
+
+PT_VAR + 1
+
+TPMA_STARTUP_CLEAR
+
+TPM_PT_HR_NV_INDEX
+
+PT_VAR + 2
+
+the number of NV Indexes currently defined
+
+TPM_PT_HR_LOADED
+
+PT_VAR + 3
+
+the number of authorization sessions currently loaded into
+TPM RAM
+
+TPM_PT_HR_LOADED_AVAIL
+
+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
+
+TPM_PT_HR_ACTIVE
+
+Page 44
+October 31, 2013
+
+PT_VAR + 5
+
+A valid implementation may return 1 even if more
+than one authorization session would fit into RAM.
+
+the number of active authorization sessions currently
+being tracked by the TPM
+This is the sum of the loaded and saved sessions.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+Capability Name
+TPM_PT_HR_ACTIVE_AVAIL
+
+Part 2: Structures
+Value
+
+Comments
+
+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
+
+TPM_PT_HR_TRANSIENT_AVAIL
+
+PT_VAR + 7
+
+A valid implementation may return 1 even if more
+than one authorization session could be created.
+
+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.
+
+TPM_PT_HR_PERSISTENT
+
+PT_VAR + 8
+
+the number of persistent objects currently loaded into
+TPM NV memory
+
+TPM_PT_HR_PERSISTENT_AVAIL
+
+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.
+
+TPM_PT_NV_COUNTERS
+
+PT_VAR + 10
+
+the number of defined NV Indexes that have NV
+TPMA_NV_COUNTER attribute SET
+
+TPM_PT_NV_COUNTERS_AVAIL
+
+PT_VAR + 11
+
+the number of additional NV Indexes that can be defined
+with
+their
+TPMA_NV_COUNTER
+and
+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 the
+TPMA_NV_COUNTER
+and
+TPMA_NV_ORDERLY
+attributes SET. 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.
+
+TPM_PT_ALGORITHM_SET
+
+PT_VAR + 12
+
+code that limits the algorithms that may be used with the
+TPM
+
+TPM_PT_LOADED_CURVES
+
+PT_VAR + 13
+
+the number of loaded ECC curves
+
+TPM_PT_LOCKOUT_COUNTER
+
+PT_VAR + 14
+
+the current value of the lockout counter (failedTries)
+
+TPM_PT_MAX_AUTH_FAIL
+
+PT_VAR + 15
+
+the number of authorization failures before DA lockout is
+invoked
+
+TPM_PT_LOCKOUT_INTERVAL
+
+PT_VAR + 16
+
+the number of seconds before the value reported by
+TPM_PT_LOCKOUT_COUNTER is decremented
+
+TPM_PT_LOCKOUT_RECOVERY
+
+PT_VAR + 17
+
+the number of seconds after a lockoutAuth failure before
+use of lockoutAuth may be attempted again
+
+TPM_PT_NV_WRITE_RECOVERY
+
+PT_VAR + 18
+
+number of milliseconds before the TPM will accept
+another command that will modify NV
+This value is an approximation and may go up or down
+over time.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 45
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+TPM_PT_AUDIT_COUNTER_0
+
+PT_VAR + 19
+
+the high-order 32 bits of the command audit counter
+
+TPM_PT_AUDIT_COUNTER_1
+
+PT_VAR + 20
+
+the low-order 32 bits of the command audit counter
+
+Page 46
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+6.14 TPM_PT_PCR (PCR Property Tag)
+The TPM_PT_PCR constants are used in TPM2_GetCapability() to indicate the property being selected
+or returned. The PCR properties can be read when capability == TPM_CAP_PCR_PROPERTIES.
+Table 23 — Definition of (UINT32) TPM_PT_PCR Constants <IN/OUT, S>
+Capability Name
+
+Value
+
+Comments
+
+TPM_PT_PCR_FIRST
+
+0x00000000
+
+bottom of the range of TPM_PT_PCR properties
+
+TPM_PT_PCR_SAVE
+
+0x00000000
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR is
+saved and restored by TPM_SU_STATE
+
+TPM_PT_PCR_EXTEND_L0
+
+0x00000001
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be extended from locality 0
+This property is only present if a locality other than 0 is
+implemented.
+
+TPM_PT_PCR_RESET_L0
+
+0x00000002
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 0
+
+TPM_PT_PCR_EXTEND_L1
+
+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.
+
+TPM_PT_PCR_RESET_L1
+
+0x00000004
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 1
+This property is only present if locality 1 is implemented.
+
+TPM_PT_PCR_EXTEND_L2
+
+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.
+
+TPM_PT_PCR_RESET_L2
+
+0x00000006
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 2
+This property is only present if localities 1 and 2 are
+implemented.
+
+TPM_PT_PCR_EXTEND_L3
+
+0x00000007
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be extended from locality 3
+This property is only present if localities 1, 2, and 3 are
+implemented.
+
+TPM_PT_PCR_RESET_L3
+
+0x00000008
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 3
+This property is only present if localities 1, 2, and 3 are
+implemented.
+
+TPM_PT_PCR_EXTEND_L4
+
+0x00000009
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be extended from locality 4
+This property is only present if localities 1, 2, 3, and 4 are
+implemented.
+
+TPM_PT_PCR_RESET_L4
+
+0x0000000A
+
+a SET bit in the TPMS_PCR_SELECT indicates that the PCR
+may be reset by TPM2_PCR_Reset() from locality 4
+This property is only present if localities 1, 2, 3, and 4 are
+implemented.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 47
+October 31, 2013
+
+ Part 2: Structures
+
+Capability Name
+reserved
+
+Trusted Platform Module Library
+
+Value
+
+Comments
+
+0x0000000B – the values in this range are reserved
+0x00000010 They correspond to values that may be used to describe
+attributes associated with the extended localities (32255).synthesize additional software localities. The meaning of
+these properties need not be the same as the meaning for the
+Extend and Reset properties above.
+
+TPM_PT_PCR_NO_INCREMENT
+
+0x00000011
+
+a SET bit in the TPMS_PCR_SELECT indicates that
+modifications to this PCR (reset or Extend) will not increment
+the pcrUpdateCounter
+
+TPM_PT_PCR_DRTM_RESET
+
+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.
+
+TPM_PT_PCR_POLICY
+
+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.
+
+TPM_PT_PCR_AUTH
+
+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.
+
+reserved
+
+0x00000015
+
+reserved for the next (2 ) TPM_PT_PCR_POLICY set
+
+reserved
+
+0x00000016
+
+reserved for the next (2 ) TPM_PT_PCR_AUTH set
+
+reserved
+
+nd
+nd
+
+nd
+
+th
+
+0x00000017 – reserved for the 2 through 255 TPM_PT_PCR_POLICY and
+0x00000210 TPM_PT_PCR_AUTH values
+th
+
+and
+
+highest
+
+allowed,
+
+th
+
+and
+
+highest
+
+allowed,
+
+reserved
+
+0x00000211
+
+reserved
+to
+the
+256 ,
+TPM_PT_PCR_POLICY set
+
+reserved
+
+0x00000212
+
+reserved
+to
+the
+256 ,
+TPM_PT_PCR_AUTH set
+
+reserved
+
+0x00000213
+
+new PCR property values may be assigned starting with this
+value
+
+TPM_PT_PCR_LAST
+
+0x00000014
+
+top of the range of TPM_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
+
+Page 48
+October 31, 2013
+
+This is an implementation-specific value. The value shown
+reflects the reference code implementation.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+6.15 TPM_PS (Platform Specific)
+The platform values in Table 24 are used for the TPM_PT_PS_FAMILY_INDICATOR.
+NOTE
+
+Values below six (6) have the same values as the purview assignments in TPM 1.2.
+
+Table 24 — Definition of (UINT32) TPM_PS Constants <OUT>
+Capability Name
+
+Value
+
+Comments
+
+TPM_PS_MAIN
+
+0x00000000
+
+not platform specific
+
+TPM_PS_PC
+
+0x00000001
+
+PC Client
+
+TPM_PS_PDA
+
+0x00000002
+
+PDA (includes all mobile devices that are not specifically cell
+phones)
+
+TPM_PS_CELL_PHONE
+
+0x00000003
+
+Cell Phone
+
+TPM_PS_SERVER
+
+0x00000004
+
+Server WG
+
+TPM_PS_PERIPHERAL
+
+0x00000005
+
+Peripheral WG
+
+TPM_PS_TSS
+
+0x00000006
+
+TSS WG
+
+TPM_PS_STORAGE
+
+0x00000007
+
+Storage WG
+
+TPM_PS_AUTHENTICATION
+
+0x00000008
+
+Authentication WG
+
+TPM_PS_EMBEDDED
+
+0x00000009
+
+Embedded WG
+
+TPM_PS_HARDCOPY
+
+0x0000000A
+
+Hardcopy WG
+
+TPM_PS_INFRASTRUCTURE
+
+0x0000000B
+
+Infrastructure WG
+
+TPM_PS_VIRTUALIZATION
+
+0x0000000C
+ Virtualization WG
+
+TPM_PS_TNC
+
+0x0000000D
+ Trusted Network Connect WG
+
+TPM_PS_MULTI_TENANT
+
+0x0000000E
+
+Multi-tenant WG
+
+TPM_PS_TC
+
+0x0000000F
+
+Technical Committee
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 49
+October 31, 2013
+
+ Part 2: Structures
+
+7
+
+Trusted Platform Module Library
+
+Handles
+
+7.1
+
+Introduction
+
+Handles are 32-bit values used to reference shielded locations of various types within the TPM.
+Table 25 — Definition of Types for Handles
+Type
+
+Name
+
+Description
+
+UINT32
+
+TPM_HANDLE
+
+Handles may refer to objects (keys or data blobs), authorization sessions (HMAC and policy), NV
+Indexes, permanent TPM locations, and PCR.
+7.2
+
+TPM_HT (Handle Types)
+
+The 32-bit handle space is divided into 256 regions of equal size with 2
+ranges represents a handle type.
+
+24
+
+values in each. Each of these
+
+The type of the entity is indicated by the MSO of its handle. The values for the MSO and the entity
+referenced are shown in Table 26.
+Table 26 — Definition of (UINT8) TPM_HT Constants <S>
+Name
+
+Value
+
+Comments
+
+TPM_HT_PCR
+
+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.
+
+TPM_HT_NV_INDEX
+
+0x01
+
+NV Index – assigned by the caller
+
+TPM_HT_HMAC_SESSION
+
+0x02
+
+HMAC Authorization Session – assigned by the TPM when the
+session is created
+
+TPM_HT_LOADED_SESSION
+
+0x02
+
+Loaded Authorization Session – used only in the context of
+TPM2_GetCapability
+This type references both loaded HMAC and loaded policy
+authorization sessions.
+
+TPM_HT_POLICY_SESSION
+
+0x03
+
+Policy Authorization Session – assigned by the TPM when the
+session is created
+
+TPM_HT_ACTIVE_SESSION
+
+0x03
+
+Active 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.
+
+TPM_HT_PERMANENT
+
+0x40
+
+Permanent Values – assigned by this specification in Table 27
+
+TPM_HT_TRANSIENT
+
+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
+
+TPM_HT_PERSISTENT
+
+0x81
+
+Persistent Objects – assigned by the TPM when a loaded transient
+object is made persistent
+
+Page 50
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+When a transient object is loaded, the TPM shall assign a handle with an MSO of TPM_HT_TRANSIENT.
+The object may be assigned a different handle each time it is loaded. The TPM shall ensure that handles
+assigned to transient objects are unique and assigned to only one transient object at a time.
+EXAMPLE
+
+If a TPM is only able to hold 4 transient objects in internal memory, it might choose to assign handles to
+those objects with the values 80 00 00 0016 – 80 00 00 0316.
+
+When a transient object is converted to a persistent object (TPM2_EvictControl()), the TPM shall validate
+that the handle provided by the caller has an MSO of TPM_HT_PERSISTENT and that the handle is not
+already assigned to a persistent object.
+A handle is assigned to a session when the session is started. The handle shall have an MSO equal to
+TPM_HT_SESSION and remain associated with that session until the session is closed or flushed. The
+TPM shall ensure that a session handle is only associated with one session at a time. When the session
+is loaded into the TPM using TPM2_LoadContext(), it will have the same handle each time it is loaded.
+EXAMPLE
+
+7.3
+
+If a TPM is only able to track 64 active sessions at a time, it could number those sessions using the
+values xx 00 01 0016 – xx 00 01 3F 16 where xx is either 02 16 or 03 16 depending on the session type.
+
+Persistent Handle Sub-ranges
+
+Persistent handles are assigned by the caller of TPM2_EvictControl(). ownerAuth or platformAuth is
+required to authorize allocation of space for a persistent object. These entities are given separate ranges
+of persistent handles so that they do not have to allocate from a common range of handles.
+NOTE
+
+While this “namespace” allocation of the handle ranges could have been handled by convention, TPM
+enforcement is used to prevent errors by the OS or malicious software from affecting the platform’s use of
+the NV memory.
+
+The Owner is allocated persistent handles in the range of 81 00 00 0016 to 81 7F FF FF16 inclusive and
+the TPM will return an error if ownerAuth is used to attempt to assign a persistent handle outside of this
+range.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 51
+October 31, 2013
+
+ Part 2: Structures
+7.4
+
+Trusted Platform Module Library
+
+TPM_RH (Permanent Handles)
+
+Table 27 lists the architecturally defined handles that cannot be changed. The handles include
+authorization handles, and special handles.
+Table 27 — Definition of (UINT32) TPM_RH Constants <IN, S>
+Name
+
+Value
+
+Type
+
+TPM_RH_FIRST
+
+0x40000000
+
+R
+
+TPM_RH_SRK
+
+0x40000000
+
+R
+
+TPM_RH_OWNER
+
+0x40000001
+
+K, A, P
+
+TPM_RH_REVOKE
+
+0x40000002
+
+R
+
+not used
+
+1
+
+TPM_RH_TRANSPORT
+
+0x40000003
+
+R
+
+not used
+
+1
+
+TPM_RH_OPERATOR
+
+0x40000004
+
+R
+
+not used
+
+1
+
+TPM_RH_ADMIN
+
+0x40000005
+
+R
+
+not used
+
+1
+
+TPM_RH_EK
+
+0x40000006
+
+R
+
+not used
+
+1
+
+TPM_RH_NULL
+
+0x40000007
+
+K, A, P
+
+a handle associated with the null hierarchy, an EmptyAuth
+authValue, and an Empty Policy authPolicy.
+
+TPM_RH_UNASSIGNED
+
+0x40000008
+
+R
+
+value reserved to the TPM to indicate a handle location that
+has not been initialized or assigned
+
+TPM_RS_PW
+
+0x40000009
+
+S
+
+authorization value
+authorization session
+
+TPM_RH_LOCKOUT
+
+0x4000000A
+
+A
+
+references the authorization associated with the dictionary
+attack lockout reset
+
+TPM_RH_ENDORSEMENT
+
+0x4000000B
+
+K, A, P
+
+references the Endorsement Primary
+endorsementAuth, and endorsementPolicy
+
+TPM_RH_PLATFORM
+
+0x4000000C
+
+K, A, P
+
+references the Platform Primary Seed (PPS), platformAuth,
+and platformPolicy
+
+TPM_RH_PLATFORM_NV
+
+0x4000000D
+
+C
+
+for phEnableNV
+
+R
+
+the top of the reserved handle area
+This is set to allow TPM2_GetCapability() to know where to
+stop. It may vary as implementations add to the permanent
+handle area.
+
+TPM_RH_LAST
+
+0x4000000D
+
+Comments
+
+not used
+
+1
+
+handle references the Storage Primary Seed (SPS), the
+ownerAuth, and the ownerPolicy
+
+used
+
+to
+
+indicate
+
+a
+
+password
+
+Seed
+
+(EPS),
+
+Type definitions:
+R – a reserved value
+K – a Primary Seed
+A – an authorization value
+P – a policy value
+S – a session handle
+C - a controlNote 1 The handle is only used in a TPM that is compatible with a previous version of this specification. It is not used
+in any command defined in this version of the specification.
+
+Page 52
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+7.5
+
+Part 2: Structures
+
+TPM_HC (Handle Value Constants)
+
+The definitions in Table 28 are used to define many of the interface data types. However, the values of
+these constants, other than PCR_FIRST, are informative and may be changed by an implementation as
+long as the values stay within the prescribed ranges for the handle type.
+NOTE
+
+PCR0 is architecturally defined to have a handle value of 0.
+
+For the reference implementation, the handle range for sessions starts at the lowest allowed value for a
+session handle. The highest value for a session handle is determined by how many active sessions are
+allowed by the implementation. The MSO of the session handle will be set according to the session type.
+A similar approach is used for transient objects with the first assigned handle at the bottom of the range
+defined by TPM_HT_TRANSIENT and the top of the range determined by the implementation-dependent
+value of MAX_LOADED_OBJECTS.
+The first assigned handle for evict objects is also at the bottom of the allowed range defined by
+TPM_HT_PERSISTENT and the top of the range determined by the implementation-dependent value of
+MAX_EVICT_OBJECTS.
+NOTE
+
+The values in Table 28 are intended to facilitate the process of making the handle larger than 32 bits in
+the future. It is intended that HR_MASK and HR_SHIFT are the only values that need change to resize
+the handle space.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 53
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Table 28 — Definition of (TPM_HANDLE) TPM_HC Constants <IN, S>
+Name
+
+Value
+
+Comments
+
+HR_HANDLE_MASK
+
+0x00FFFFFF
+
+to mask off the HR
+
+HR_RANGE_MASK
+
+0xFF000000
+
+to mask off the variable
+part
+
+HR_SHIFT
+
+24
+
+HR_PCR
+
+(TPM_HT_PCR << HR_SHIFT)
+
+HR_HMAC_SESSION
+
+(TPM_HT_HMAC_SESSION << HR_SHIFT)
+
+HR_POLICY_SESSION
+
+(TPM_HT_POLICY_SESSION << HR_SHIFT)
+
+HR_TRANSIENT
+
+(TPM_HT_TRANSIENT << HR_SHIFT)
+
+HR_PERSISTENT
+
+(TPM_HT_PERSISTENT << HR_SHIFT)
+
+HR_NV_INDEX
+
+(TPM_HT_NV_INDEX << HR_SHIFT)
+
+HR_PERMANENT
+
+(TPM_HT_PERMANENT << HR_SHIFT)
+
+PCR_FIRST
+
+(HR_PCR + 0)
+
+first PCR
+
+PCR_LAST
+
+(PCR_FIRST + IMPLEMENTATION_PCR-1)
+
+last PCR
+
+HMAC_SESSION_FIRST
+
+(HR_HMAC_SESSION + 0)
+
+first HMAC session
+
+HMAC_SESSION_LAST
+
+(HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1)
+
+last HMAC session
+
+LOADED_SESSION_FIRST HMAC_SESSION_FIRST
+
+used in GetCapability
+
+LOADED_SESSION_LAST
+
+HMAC_SESSION_LAST
+
+used in GetCapability
+
+POLICY_SESSION_FIRST
+
+(HR_POLICY_SESSION + 0)
+
+first policy session
+
+POLICY_SESSION_LAST
+
+(POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1)
+ last policy session
+
+TRANSIENT_FIRST
+
+(HR_TRANSIENT + 0)
+
+first transient object
+
+ACTIVE_SESSION_FIRST
+
+POLICY_SESSION_FIRST
+
+used in GetCapability
+
+ACTIVE_SESSION_LAST
+
+POLICY_SESSION_LAST
+
+used in GetCapability
+
+TRANSIENT_LAST
+
+(TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1)
+
+last transient object
+
+PERSISTENT_FIRST
+
+(HR_PERSISTENT + 0)
+
+first persistent object
+
+PERSISTENT_LAST
+
+(PERSISTENT_FIRST + 0x00FFFFFF)
+
+last persistent object
+
+PLATFORM_PERSISTENT
+
+(PERSISTENT_FIRST + 0x00800000)
+
+first platform persistent
+object
+
+NV_INDEX_FIRST
+
+(HR_NV_INDEX + 0)
+
+first allowed NV Index
+
+NV_INDEX_LAST
+
+(NV_INDEX_FIRST + 0x00FFFFFF)
+
+last allowed NV Index
+
+PERMANENT_FIRST
+
+TPM_RH_FIRST
+
+PERMANENT_LAST
+
+TPM_RH_LAST
+
+Page 54
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Attribute Structures
+
+8
+8.1
+
+Description
+
+Attributes are expressed as bit fields of varying size. An attribute field structure may be 1, 2, or 4 octets in
+length.
+The bit numbers for an attribute structure are assigned with the number 0 assigned to the least-significant
+bit of the structure and the highest number assigned to the most-significant bit of the structure.
+The least significant bit is determined by treating the attribute structure as an integer. The least-significant
+bit would be the bit that is set when the value of the integer is 1.
+When any reserved bit in an attribute is SET, the TPM shall return TPM_RC_RESERVED_BITS. This
+response code is not shown in the tables for attributes.
+8.2
+
+TPMA_ALGORITHM
+
+This structure defines the attributes of an algorithm.
+Each algorithm has a fundamental attribute: asymmetric, symmetric, or hash. In some cases (e.g.,
+TPM_ALG_RSA or TPM_ALG_AES), this is the only attribute.
+A mode, method, or scheme may have an associated asymmetric, symmetric, or hash algorithm.
+Table 29 — Definition of (UINT32) TPMA_ALGORITHM Bits
+Bit
+
+Name
+
+Definition
+
+0
+
+asymmetric
+
+SET (1): an asymmetric algorithm with public and private portions
+CLEAR (0): not an asymmetric algorithm
+
+1
+
+symmetric
+
+SET (1): a symmetric block cipher
+CLEAR (0): not a symmetric block cipher
+
+2
+
+hash
+
+SET (1): a hash algorithm
+CLEAR (0): not a hash algorithm
+
+3
+
+object
+
+SET (1): an algorithm that may be used as an object type
+CLEAR (0): an algorithm that is not used as an object type
+
+7:4
+
+Reserved
+
+8
+
+signing
+
+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
+
+9
+
+encrypting
+
+SET (1): an encryption/decryption algorithm. The setting of asymmetric,
+symmetric, and hash will indicate the type of encryption/decryption algorithm.
+CLEAR (0): not an encryption/decryption algorithm
+
+10
+
+method
+
+SET (1): a method such as a key derivative function (KDF)
+CLEAR (0): not a method
+
+31:11 Reserved
+
+8.3
+8.3.1
+
+TPMA_OBJECT (Object Attributes)
+Introduction
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 55
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+This attribute structure indicates an object’s use, its authorization types, and it relationship to other
+objects.
+The state of the attributes is determined when the object is created and they are never changed by the
+TPM. Additionally, the setting of these structures is reflected in the integrity value of the private area of an
+object in order to allow the TPM to detect modifications of the Protected Object when stored off the TPM.
+8.3.2
+
+Structure Definition
+Table 30 — Definition of (UINT32) TPMA_OBJECT Bits
+
+Bit
+
+Name
+
+Definition
+
+0
+
+Reserved
+
+shall be zero
+
+1
+
+fixedTPM
+
+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.
+
+2
+
+stClear
+
+SET (1): Previously saved contexts of this object may not be loaded after
+Startup(CLEAR).
+CLEAR (0): Saved contexts of this object may be used after a
+Shutdown(STATE) and subsequent Startup().
+
+3
+
+Reserved
+
+shall be zero
+
+4
+
+fixedParent
+
+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.
+
+5
+
+sensitiveDataOrigin
+
+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.
+
+6
+
+userWithAuth
+
+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.
+
+7
+
+adminWithPolicy
+
+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.
+
+9:8
+
+Reserved
+
+shall be zero
+
+10
+
+noDA
+
+SET (1): The object is not subject to dictionary attack protections.
+CLEAR (0): The object is subject to dictionary attack protections.
+
+11
+
+encryptedDuplication
+
+SET (1): If the object is duplicated, then symmetricAlg shall not be
+TPM_ALG_NULL and newParentHandle shall not be TPM_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 TPM_RH_NULL.
+
+15:12 Reserved
+16
+
+restricted
+
+Page 56
+October 31, 2013
+
+shall be zero
+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.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Bit
+
+Name
+
+Definition
+
+17
+
+decrypt
+
+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.
+
+18
+
+sign
+
+SET (1): 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.
+
+31:19 Reserved
+
+8.3.3
+8.3.3.1
+
+shall be zero
+
+Attribute Descriptions
+Introduction
+
+The following remaining paragraphs in this clause describe the use and settings for each of the
+TPMA_OBJECT attributes. The description includes checks that are performed on the objectAttributes
+when an object is created, when it is loaded, and when it is imported. In these descriptions:
+Creation –
+
+indicates
+settings
+for
+TPM2_CreatePrimary()
+
+the
+
+template
+
+parameter
+
+in
+
+TPM2_Create()
+
+or
+
+Load
+
+–
+
+indicates settings for the inPublic parameter in TPM2_Load()
+
+Import
+
+–
+
+indicates settings for the objectPublic parameter in TPM2_Import()
+
+External
+
+–
+
+indicates settings that apply to the inPublic parameter in TPM2_LoadExternal() if both the
+public and sensitive portions of the object are loaded
+
+NOTE
+
+For TPM2_LoadExternal() when only the public portion of the object is loaded, the only attribute checks
+are the checks in the validation code following Table 30 and the reserved attributes check.
+
+For any consistency error of attributes in TPMA_OBJECT, the TPM shall return TPM_RC_ATTRIBUTES.
+8.3.3.2
+
+Bit[1] – fixedTPM
+
+When SET, the object cannot be duplicated for use on a different TPM, either directly or indirectly and the
+Qualified Name of the object cannot change. When CLEAR, the object’s Qualified Name may change if
+the object or an ancestor is duplicated.
+NOTE
+
+This attribute is the logical inverse of the migratable attribute in 1.2. That is, when this attribute is C LEAR,
+it is the equivalent to a 1.2 object with migratable SET.
+
+Creation –
+
+If fixedTPM is SET in the object's parent, then fixedTPM and fixedParent shall both be
+set to the same value in template. If fixedTPM is CLEAR in the parent, this attribute shall
+also be CLEAR in template.
+NOTE
+
+For a Primary Object, the parent is considered to have fixedTPM SET.
+
+Load
+
+–
+
+If fixedTPM is SET in the object's parent, then fixedTPM and fixedParent shall both be
+set to the same value. If fixedTPM is CLEAR in the parent, this attribute shall also be
+CLEAR.
+
+Import
+
+–
+
+shall be CLEAR
+
+External
+
+–
+
+shall be CLEAR if both the public and sensitive portions are loaded or if fixedParent is
+CLEAR, otherwise may be SET or CLEAR
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 57
+October 31, 2013
+
+ Part 2: Structures
+8.3.3.3
+
+Trusted Platform Module Library
+
+Bit[2] – stClear
+
+If this attribute is SET, then saved contexts of this object will be invalidated on
+TPM2_Startup(TPM_SU_CLEAR). If the attribute is CLEAR, then the TPM shall not invalidate the saved
+context if the TPM received TPM2_Shutdown(TPM_SU_STATE). If the saved state is valid when checked
+at the next TPM2_Startup(), then the TPM shall continue to be able to use the saved contexts.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.4
+
+Bit[4] – fixedParent
+
+If this attribute is SET, the object’s parent may not be changed. That is, this object may not be the object
+of a TPM2_Duplicate(). If this attribute is CLEAR, then this object may be the object of a
+TPM2_Duplicate().
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+shall be CLEAR
+
+External
+
+–
+
+shall be CLEAR if both the public and sensitive portions are loaded; otherwise it may be
+SET or CLEAR
+
+8.3.3.5
+
+Bit[5] – sensitiveDataOrigin
+
+This attribute is SET for any key that was generated by TPM in TPM2_Create() or
+TPM2_CreatePrimary(). If CLEAR, it indicates that the sensitive part of the object (other than the
+obfuscation value) was provided by the caller.
+NOTE 1
+
+If the fixedTPM attribute is SET, then this attribute is authoritative and accurately reflects the source of
+the sensitive area data. If the fixedTPM attribute is CLEAR, then validation of this attribute requires
+evaluation of the properties of the ancestor keys.
+
+Creation –
+
+If inSensitive.sensitive.data.size is zero, then this attribute shall be SET in the template;
+otherwise, it shall be CLEAR in the template.
+
+NOTE 2
+
+The inSensitive.sensitive.data.size parameter is required to be zero for an asymmetric key so
+sensitiveDataOrigin is required to be SET.
+
+NOTE 3
+
+The inSensitive.sensitive.data.size parameter may not be zero for a data object so sensitiveDataOrigin is
+required to be CLEAR. A data object has type = TPM_ALG_KEYEDHASH and its sign and decrypt
+attributes are CLEAR.
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+Page 58
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.3.3.6
+
+Part 2: Structures
+
+Bit[6] – userWithAuth
+
+If SET, authorization for operations that require USER role authorization may be given if the caller
+provides proof of knowledge of the authValue of the object with an HMAC authorization session or a
+password.
+If this attribute is CLEAR, then then HMAC or password authorizations may not be used for USER role
+authorizations.
+NOTE 1
+
+Regardless of the setting of this attribute, authorizations for operations th at require USER role
+authorizations may be provided with a policy session that satisfies the object's authPolicy.
+
+NOTE 2
+
+Regardless of the setting of this attribute, the authValue may be referenced in a policy session or used to
+provide the bind value in TPM2_StartAuthSession(). However, if userWithAuth is CLEAR, then the object
+may be used as the bind object in TPM2_StartAuthSession() but the session cannot be used to authorize
+actions on the object. If this were allowed, then the userWithAuth control could be circumvented simply by
+using the object as the bind object.
+
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.7
+
+Bit[7] – adminWithPolicy
+
+If CLEAR, authorization for operations that require ADMIN role may be given if the caller provides proof of
+knowledge of the authValue of the object with an HMAC authorization session or a password.
+If this attribute is SET, then then HMAC or password authorizations may not be used for ADMIN role
+authorizations.
+NOTE 1
+
+Regardless of the setting of this attribute, operations that require ADMIN role authorization may be
+provided by a policy session that satisfies the object's authPolicy.
+
+NOTE 2
+
+This attribute is similar to userWithAuth but the logic is a bit different. When userWithAuth is CLEAR, the
+authValue may not be used for USER mode authorizations. When adminWithPolicy is CLEAR, it means
+that the authValue may be used for ADMIN role. Policy may always be used regardless of t he setting of
+userWithAuth or adminWithPolicy.
+
+Actions that always require policy (TPM2_Duplicate()) are not affected by the setting of this attribute.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.8
+
+Bit[10] – noDA
+
+If SET, then authorization failures for the object do not affect the dictionary attack protection logic and
+authorization of the object is not blocked if the TPM is in lockout.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 59
+October 31, 2013
+
+ Part 2: Structures
+8.3.3.9
+
+Trusted Platform Module Library
+
+Bit[11] – encryptedDuplication
+
+If SET, then when the object is duplicated, the sensitive portion of the object is required to be encrypted
+with an inner wrapper and the new parent shall be an asymmetric key and not TPM_RH_NULL
+NOTE 1
+
+Enforcement of these requirements in TPM2_Duplicate() is by not allowing symmetricAlg to be
+TPM_ALG_NULL and newParentHandle may not be TPM_RH_NULL.
+
+This attribute shall not be SET in any object that has fixedTPM SET.
+NOTE 2
+
+This requirement means that encryptedDuplication may not be SET if the object cannot be directly or
+indirectly duplicated.
+
+If an object's parent has fixedTPM SET, and the object is duplicable (fixedParent == CLEAR), then
+encryptedDuplication may be SET or CLEAR in the object.
+NOTE 3
+
+This allows the object at the boundary between duplicable and non -duplicable objects to have either
+setting.
+
+If an object's parent has fixedTPM CLEAR, then the object is required to have the same setting of
+encryptedDuplication as its parent.
+NOTE 4
+
+This requirement forces all
+encryptedDuplication setting.
+
+duplicable
+
+objects
+
+in
+
+a
+
+duplication
+
+group
+
+to
+
+have
+
+the
+
+same
+
+Creation –
+
+shall be CLEAR if fixedTPM is SET. If fixedTPM is CLEAR, then this attribute shall have
+the same value as its parent unless fixedTPM is SET in the object's parent, in which
+case, it may be SET or CLEAR.
+
+Load
+
+–
+
+shall be CLEAR if fixedTPM is SET. If fixedTPM is CLEAR, then this attribute shall have
+the same value as its parent, unless fixedTPM is SET the parent, in which case, it may
+be SET or CLEAR.
+
+Import
+
+–
+
+if fixedTPM is SET in the object's new parent, then this attribute may be SET or CLEAR,
+otherwise, it shall have the same setting as the new parent.
+
+External
+
+–
+
+may be SET or CLEAR.
+
+8.3.3.10
+
+Bit[16] – restricted
+
+This this attribute modifies the decrypt and sign attributes of an object.
+NOTE
+
+A key with this object CLEAR may not be a parent for another object.
+
+Creation –
+
+shall be CLEAR in template if neither sign nor decrypt is SET in template.
+
+Load
+
+–
+
+shall be CLEAR if neither sign nor decrypt is SET in the object
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+shall be CLEAR
+
+Page 60
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.3.3.11
+
+Part 2: Structures
+
+Bit[17] – decrypt
+
+When SET, the private portion of this key can be used to decrypt an external blob. If restricted is SET,
+then the TPM will return an error if the external decrypted blob is not formatted as appropriate for the
+command.
+NOTE 1
+
+Since TPM-generated keys and sealed data will contain a hash and a structure tag, the TPM can ensure
+that it is not being used to improperly decrypt and return sensitive data that should not be returned. The
+only type of data that may be returned after decryption is a Sealed Data Object (a keyedHash object with
+decrypt and sign CLEAR).
+
+When restricted is CLEAR, there are no restrictions on the use of the private portion of the key for
+decryption and the key may be used to decrypt and return any structure encrypted by the public portion of
+the key.
+NOTE 2
+
+A key with this attribute SET may be a parent for another object if restricted is SET and sign is CLEAR.
+
+If decrypt is SET on an object with type set to TPM_ALG_KEYEDHASH, it indicates that the object is an
+XOR encryption key.
+Creation –
+
+may be SET or CLEAR in template
+
+Load
+
+–
+
+may be SET or CLEAR
+
+Import
+
+–
+
+may be SET or CLEAR
+
+External
+
+–
+
+may be SET or CLEAR
+
+8.3.3.12
+
+Bit[18] – sign
+
+When this attribute is SET, the private portion of this key may be used to sign a digest. If restricted is
+SET, then the key may only be used to sign a digest that was computed by the TPM. A restricted signing
+key may be used to sign a TPM-generated digest. If a structure is generated by the TPM, it will begin with
+TPM_GENERATED_VALUE and the TPM may sign the digest of that structure. If the data is externally
+supplied and has TPM_GENERATED_VALUE as its first octets, then the TPM will not sign a digest of
+that data with a restricted signing key.
+If restricted is CLEAR, then the key may be used to sign any digest, whether generated by the TPM or
+externally provided.
+NOTE 1
+
+Some asymmetric algorithms may not support both sign and decrypt being SET in the same key.
+
+If sign is SET on an object with type set to TPM_ALG_KEYEDHASH, it indicates that the object is an
+HMAC key.
+NOTE 2
+
+A key with this attribute SET may not be a parent for another object.
+
+Creation –
+
+shall not be SET if decrypt and restricted are both SET
+
+Load
+
+–
+
+shall not be SET if decrypt and restricted are both SET
+
+Import
+
+–
+
+shall not be SET if decrypt and restricted are both SET
+
+External
+
+–
+
+shall not be SET if decrypt and restricted are both SET
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 61
+October 31, 2013
+
+ Part 2: Structures
+8.4
+
+Trusted Platform Module Library
+
+TPMA_SESSION (Session Attributes)
+
+This octet in each session is used to identify the session type, indicate its relationship to any handles in
+the command, and indicate its use in parameter encryption.
+Table 31 — Definition of (UINT8) TPMA_SESSION Bits <IN/OUT>
+Bit
+
+Name
+
+Meaning
+
+0
+
+continueSession
+
+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.
+
+1
+
+auditExclusive
+
+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.
+CLEAR (0): If audit is CLEAR, then this field is reserved but the error is
+TPM_RC_ATTRIBUTES rather than TPM_RC_RESERVED_BITS.
+See "Exclusive Audit Session" clause in Part 1.
+
+2
+
+auditReset
+
+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.
+CLEAR (0): If audit is CLEAR, then this field is reserved but the error is
+TPM_RC_ATTRIBUTES rather than TPM_RC_RESERVED_BITS. This setting is
+always used for a response.
+
+4:3
+
+Reserved
+
+shall be CLEAR
+
+decrypt
+
+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 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.
+
+5
+
+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_).
+
+Page 62
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Bit
+
+Name
+
+Meaning
+
+6
+
+encrypt
+
+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
+Part 1 of this specification.
+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_).
+
+7
+
+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.
+
+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.
+
+8.5
+
+TPMA_LOCALITY (Locality Attribute)
+
+In a TPMS_CREATION_DATA structure, this structure is used to indicate the locality of the command that
+created the object. No more than one of the locality attributes shall be set in the creation data.
+When used in TPM2_PolicyLocality(), this structure indicates which localities are approved by the policy.
+When a policy is started, all localities are allowed. If TPM2_PolicyLocality() is executed, it indicates that
+the command may only be executed at specific localities. More than one locality may be selected.
+EXAMPLE 1
+
+TPM_LOC_TWO would indicate that only locality 2 is authorized.
+
+EXAMPLE 2
+
+TPM_LOC_ONE + TPM_LOC_TWO would indicate that locality 1 or 2 is authorized.
+
+EXAMPLE 3
+
+TPM_LOC_FOUR + TPM_LOC_THREE would indicate that localities 3 or 4 are authorized.
+
+EXAMPLE 4
+
+A value of 21 16 would represent a locality of 33.
+
+NOTE
+
+Locality values of 5 through 31 are not selectable.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 63
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+If Extended is non-zero, then an extended locality is indicated and the TPMA_LOCALITY contains an
+integer value.
+Table 32 — Definition of (UINT8) TPMA_LOCALITY Bits <IN/OUT>
+Bit
+
+Name
+
+Definition
+
+0
+
+TPM_LOC_ZERO
+
+1
+
+TPM_LOC_ONE
+
+2
+
+TPM_LOC_TWO
+
+3
+
+TPM_LOC_THREE
+
+4
+
+TPM_LOC_FOUR
+
+7:5
+
+8.6
+
+Extended
+
+If any of these bits is set, an extended locality is indicated
+
+TPMA_PERMANENT
+
+The attributes in this structure are persistent and are not changed as a result of _TPM_Init or any
+TPM2_Startup(). Some of the attributes in this structure may change as the result of specific Protected
+Capabilities.
+This
+structure
+may
+be
+read
+using
+TPM2_GetCapability(capability
+=
+TPM_CAP_TPM_PROPERTIES, property = TPM_PT_PERMANENT).
+Table 33 — Definition of (UINT32) TPMA_PERMANENT Bits <OUT>
+Bit
+
+Parameter
+
+Description
+
+0
+
+ownerAuthSet
+
+SET (1): TPM2_HierarchyChangeAuth() with ownerAuth has been executed since
+the last TPM2_Clear().
+CLEAR (0): ownerAuth has not been changed since TPM2_Clear().
+
+1
+
+endorsementAuthSet
+
+SET (1): TPM2_HierarchyChangeAuth() with endorsementAuth has been executed
+since the last TPM2_Clear().
+CLEAR (0): endorsementAuth has not been changed since TPM2_Clear().
+
+2
+
+lockoutAuthSet
+
+SET (1): TPM2_HierarchyChangeAuth() with lockoutAuth has been executed since
+the last TPM2_Clear().
+CLEAR (0): lockoutAuth has not been changed since TPM2_Clear().
+
+7:3
+8
+
+Reserved
+disableClear
+
+SET (1): TPM2_Clear() is disabled.
+CLEAR (0): TPM2_Clear() is enabled.
+NOTE
+
+See “TPM2_ClearControl” in Part 3 of this specification for details on changing
+this attribute.
+
+9
+
+inLockout
+
+SET (1): The TPM is in lockout and commands that require authorization with other
+than platformAuth will not succeed.
+
+10
+
+tpmGeneratedEPS
+
+SET (1): The EPS was created by the TPM.
+CLEAR (0): The EPS was created outside of the TPM using a manufacturerspecific process.
+
+31:11 Reserved
+
+Page 64
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.7
+
+Part 2: Structures
+
+TPMA_STARTUP_CLEAR
+
+These attributes are set to their default state on reset on each TPM Reset or TPM Restart. The attributes
+are preserved on TPM Resume.
+On each TPM2_Startup(TPM_SU_CLEAR), the TPM will set these attributes to their indicated defaults.
+This structure may be read using TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES,
+property = TPM_PT_STARTUP_CLEAR).
+Some of attributes may be changed as the result of specific Protected Capabilities.
+Table 34 — Definition of (UINT32) TPMA_STARTUP_CLEAR Bits <OUT>
+Bit
+0
+
+Parameter
+
+Description
+
+phEnable
+
+SET (1): (default) 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 NV Indexes and persistent objects,
+cannot be used.
+NOTE
+
+1
+
+shEnable
+
+SET (1): (default) The Storage hierarchy is enabled and ownerAuth or ownerPolicy
+may be used for authorization.
+CLEAR (0): ownerAuth and ownerPolicy may not be used for authorizations, and
+objects in the Storage hierarchy, including NV Indexes and persistent objects,
+cannot be used.
+NOTE
+
+2
+
+ehEnable
+
+phEnableNV
+
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on
+changing this attribute.
+
+SET (1): (default) The EPS hierarchy is enabled and endorsementAuth may be
+used to authorize commands.
+CLEAR (0): endorsementAuth and endorsementPolicy may not be used for
+authorizations, and objects in the endorsement hierarchy, including persistent
+objects, cannot be used.
+NOTE
+
+3
+
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on
+changing this attribute.
+
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on
+changing this attribute.
+
+SET (1): (default) 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 (TPM_RC_HANDLE). The platform cannot
+define
+(TPM_RC_HIERARCHY) or undefined (TPM_RC_HANDLE) indices.
+NOTE
+See “TPM2_HierarchyControl” in Part 3 of this specification for details on changing
+this attribute.
+NOTE
+read refers to these commands: TPM2_NV_Read, TPM2_NV_ReadPublic, TPM_NV_Certify,
+TPM2_PolicyNV
+write refers to thse commands: TPM2_NV_Write, TPM2_NV_Increment, TPM2_NV_Extend,
+TPM2_NV_SetBits
+NOTE The TPM must query the index TPMA_PLATFORM_CREATE attribute to determine
+whether phEnableNV is applicable. Since the TPM will return TPM_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.
+
+30:4 Reserved
+
+Family “2.0”
+Level 00 Revision 00.99
+
+shall be zero
+
+Published
+Copyright © TCG 2006-2013
+
+Page 65
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Bit
+
+Parameter
+
+Description
+
+31
+
+orderly
+
+SET (1): The TPM received a TPM2_Shutdown() and a matching TPM2_Startup().
+CLEAR (0): TPM2_Startup(TPM_SU_CLEAR) was not preceded by a
+TPM2_Shutdown() of any type.
+NOTE
+
+8.8
+
+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_Startup(TPM_SU_STATE)
+was
+not
+preceded
+by
+TPM2_State_Save(TPM_SU_STATE).
+
+TPMA_MEMORY
+
+This structure of this attribute is used to report the memory management method used by the TPM for
+transient
+objects
+and
+authorization
+sessions.
+This
+structure
+may be
+read
+using
+TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES, property = TPM_PT_MEMORY).
+If the RAM memory is shared, then context save of a session may make it possible to load an additional
+transient object.
+Table 35 — Definition of (UINT32) TPMA_MEMORY Bits <Out>
+Bit
+
+Name
+
+Definition
+
+0
+
+sharedRAM
+
+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
+
+1
+
+sharedNV
+
+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
+
+2
+
+objectCopiedToRam
+
+SET (1): indicates that the TPM copies persistent objects to a transient-object
+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 transient-object slots when
+persistent objects are referenced
+
+31:3
+
+Reserved
+
+shall be zero
+
+Page 66
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+8.9
+
+Part 2: Structures
+
+TPMA_CC (Command Code Attributes)
+
+8.9.1
+
+Introduction
+
+This structure defines the attributes of a command from a context management perspective. The fields of
+the structure indicate to the TPM Resource Manager (TRM) the number of resources required by a
+command and how the command affects the TPM’s resources.
+This structure is only used in a list returned by the TPM in response to TPM2_GetCapability(capability =
+TPM_CAP_COMMANDS).
+For a command to the TPM, only the commandIndex field and V attribute are allowed to be non-zero.
+8.9.2
+
+Structure Definition
+Table 36 — Definition of (TPM_CC) TPMA_CC Bits <OUT>
+
+Bit
+15:0
+
+Name
+
+Definition
+
+commandIndex
+
+indicates the command being selected
+
+21:16 Reserved
+
+shall be zero
+
+22
+
+nv
+
+SET (1): indicates that the command may write to NV
+CLEAR (0): indicates that the command does not write to NV
+
+23
+
+extensive
+
+SET (1): This command could flush any number of loaded contexts.
+CLEAR (0): no additional changes other than indicated by the flushed attribute
+
+24
+
+flushed
+
+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.
+
+27:25 cHandles
+
+indicates the number of the handles in the handle area for this command
+
+28
+
+rHandle
+
+SET (1): indicates the presence of the handle area in the input
+
+29
+
+V
+
+SET (1): indicates that the command is vendor-specific
+CLEAR (0): indicates that the command is defined in a version of this
+specification
+
+31:30 Res
+
+8.9.3
+8.9.3.1
+
+allocated for software; shall be zero
+
+Field Descriptions
+Bits[15:0] – commandIndex
+
+This is the command index of the command in the set of commands. The two sets are defined by the V
+attribute. If V is zero, then the commandIndex shall be in the set of commands defined in a version of this
+specification. If V is one, then the meaning of commandIndex is as determined by the TPM vendor.
+8.9.3.2
+
+Bit[22] – nv
+
+If this attribute is SET, then the TPM may perform an NV write as part of the command actions. This write
+is independent of any write that may occur as a result of dictionary attack protection. If this attribute is
+CLEAR, then the TPM shall not perform an NV write as part of the command actions.
+8.9.3.3
+
+Bit[23] – extensive
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 67
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+If this attribute is SET, then the TPM may flush many transient objects as a side effect of this command.
+In Part 3, a command that has this attribute is indicated by using a “{E}” decoration in the “Description”
+column of the commandCode parameter.
+EXAMPLE
+
+See “TPM2_Clear” in Part 3.
+
+NOTE
+
+The “{E}” decoration may be combined with other decorations such as “{NV}” in which case the decoration
+would be “{NV E}.”
+
+8.9.3.4
+
+Bit[24] – flushed
+
+If this attribute is SET, then the TPM will flush transient objects as a side effect of this command. Any
+transient objects listed in the handle area of the command will be flushed from TPM memory. Handles
+associated with persistent objects, sessions, PCR, or other fixed TPM resources are not flushed.
+NOTE
+
+The TRM is expected to use this value to determine how many objects are loaded into transient TPM
+memory.
+
+NOTE
+
+The “{F}” decoration may be combined with other decorations such as “{NV}” in which case the decoration
+would be “{NV F}.”
+
+If this attribute is SET for a command, and the handle of the command is associated with a hierarchy
+(TPM_RH_PLATFORM, TPM_RH_OWNER, or TPM_RH_ENDORSEMENT), all loaded objects in the
+indicated hierarchy are flushed.
+The TRM is expected to know the behaviour of TPM2_ContextSave(), and sessions are flushed when
+context saved, but objects are not. The flushed attribute for that command shall be CLEAR.
+In Part 3, a command that has this attribute is indicated by using a “{F}” decoration in the “Description”
+column of the commandCode parameter.
+EXAMPLE
+
+8.9.3.5
+
+See “TPM2_SequenceComplete” in Part 3.”
+
+Bits[27:25] – cHandles
+
+This field indicates the number of handles in the handle area of the command. This number allows the
+TRM to enumerate the handles in the handle area and find the position of the authorizations (if any).
+8.9.3.6
+
+Bit[28] – rHandle
+
+If this attribute is SET, then the response to this command has a handle area. This area will contain no
+more than one handle. This field is necessary to allow the TRM to locate the parameterSize field in the
+response, which is then used to locate the authorizations.
+NOTE
+
+The TRM is expected to “virtualize” the handle value for any returned handle.
+
+Page 68
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+A TPM command is only allowed to have one handle in the session area.
+8.9.3.7
+
+Bit[29] – V
+
+When this attribute is SET, it indicates that the command operation is defined by the TPM vendor. When
+CLEAR, it indicates that the command is defined by a version of this specification.
+8.9.3.8
+
+Bits[31:30] – Res
+
+This field is reserved for system software. This field is required to be zero for a command to the TPM.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 69
+October 31, 2013
+
+ Part 2: Structures
+
+9
+
+Trusted Platform Module Library
+
+Interface Types
+
+9.1
+
+Introduction
+
+This clause contains definitions for interface types. An interface type is type checked when it is
+unmarshaled. These types are based on an underlying type that is indicated in the table title by the value
+in parentheses. When an interface type is used, the base type is unmarshaled and then checked to see if
+it has one of the allowed values.
+9.2
+
+TPMI_YES_NO
+
+This interface type is used in place of a Boolean type in order to eliminate ambiguity in the handling of a
+octet that conveys a single bit of information. This type only has two allowed values, YES (1) and NO (0).
+NOTE
+
+This list is not used as input to the TPM.
+
+Table 37 — Definition of (BYTE) TPMI_YES_NO Type
+Value
+
+Description
+
+NO
+
+a value of 0
+
+YES
+
+a value of 1
+
+#TPM_RC_VALUE
+
+9.3
+
+TPMI_DH_OBJECT
+
+The TPMI_DH_OBJECT interface type is a handle that references a loaded object. The handles in this
+set are used to refer to either transient or persistent object. The range of these values would change
+according to the TPM implementation.
+NOTE
+
+These interface types should not be used by system software to qualify the keys produced by the TPM.
+The value returned by the TPM shall be used to reference the object.
+
+Table 38 — Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type
+Values
+
+Comments
+
+{TRANSIENT_FIRST:TRANSIENT_LAST}
+
+allowed range for transient objects
+
+{PERSISTENT_FIRST:PERSISTENT_LAST}
+
+allowed range for persistent objects
+
++TPM_RH_NULL
+
+the conditional value
+
+#TPM_RC_VALUE
+
+Page 70
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+9.4
+
+Part 2: Structures
+
+TPMI_DH_PERSISTENT
+
+The TPMI_DH_PERSISTENT interface type is a handle that references a location for a transient object.
+This type is used in TPM2_EvictControl() to indicate the handle to be assigned to the persistent object.
+Table 39 — Definition of (TPM_HANDLE) TPMI_DH_PERSISTENT Type
+Values
+
+Comments
+
+{PERSISTENT_FIRST:PERSISTENT_LAST}
+
+allowed range for persistent objects
+
+#TPM_RC_VALUE
+
+9.5
+
+TPMI_DH_ENTITY
+
+The TPMI_DH_ENTITY interface type is TPM-defined values that are used to indicate that the handle
+refers to an authValue. The range of these values would change according to the TPM implementation.
+Table 40 — Definition of (TPM_HANDLE) TPMI_DH_ENTITY Type <IN>
+Values
+
+Comments
+
+TPM_RH_OWNER
+TPM_RH_ENDORSEMENT
+TPM_RH_PLATFORM
+TPM_RH_LOCKOUT
+{TRANSIENT_FIRST : TRANSIENT_LAST}
+
+range of object handles
+
+{PERSISTENT_FIRST : PERSISTENT_LAST}
+{NV_INDEX_FIRST : NV_INDEX_LAST}
+{PCR_FIRST : PCR_LAST}
++TPM_RH_NULL
+
+conditional value
+
+#TPM_RC_VALUE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 71
+October 31, 2013
+
+ Part 2: Structures
+9.6
+
+Trusted Platform Module Library
+
+TPMI_DH_PCR
+
+This interface type consists of the handles that may be used as PCR references. The upper end of this
+range of values would change according to the TPM implementation.
+NOTE 1
+
+Typically, the 0 th PCR will have a handle value of zero.
+
+NOTE 2
+
+The handle range for PCR is defined to be the same as the handle range for PCR in previous versions of
+TPM specifications.
+
+Table 41 — Definition of (TPM_HANDLE) TPMI_DH_PCR Type <IN>
+Values
+
+Comments
+
+{PCR_FIRST:PCR_LAST}
++TPM_RH_NULL
+
+conditional value
+
+#TPM_RC_VALUE
+
+9.7
+
+TPMI_SH_AUTH_SESSION
+
+The TPMI_SH_AUTH_SESSION interface type is TPM-defined values that are used to indicate that the
+handle refers to an authorization session.
+Table 42 — Definition of (TPM_HANDLE) TPMI_SH_AUTH_SESSION Type <IN/OUT>
+Values
+
+Comments
+
+{HMAC_SESSION_FIRST : HMAC_SESSION_LAST}
+
+range of HMAC authorization session handles
+
+{POLICY_SESSION_FIRST: POLICY_SESSION_LAST}
+
+range of policy authorization session handles
+
++TPM_RS_PW
+
+a password authorization
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+9.8
+
+TPMI_SH_HMAC
+
+This interface type is used for an authorization handle when the authorization session uses an HMAC.
+Table 43 — Definition of (TPM_HANDLE) TPMI_SH_HMAC Type <IN/OUT>
+Values
+
+Comments
+
+{HMAC_SESSION_FIRST: HMAC_SESSION_LAST}
+
+range of HMAC authorization session handles
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+9.9
+
+TPMI_SH_POLICY
+
+This interface type is used for a policy handle when it appears in a policy command.
+Table 44 — Definition of (TPM_HANDLE) TPMI_SH_POLICY Type <IN/OUT>
+Values
+
+Comments
+
+{POLICY_SESSION_FIRST: POLICY_SESSION_LAST}
+
+range of policy authorization session handles
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+Page 72
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.10 TPMI_DH_CONTEXT
+This type defines the handle values that may be used in TPM2_ContextSave() or TPM2_Flush().
+Table 45 — Definition of (TPM_HANDLE) TPMI_DH_CONTEXT Type
+Values
+
+Comments
+
+{HMAC_SESSION_FIRST : HMAC_SESSION_LAST}
+{POLICY_SESSION_FIRST:POLICY_SESSION_LAST}
+{TRANSIENT_FIRST:TRANSIENT_LAST}
+#TPM_RC_VALUE
+
+9.11 TPMI_RH_HIERARCHY
+The TPMI_RH_HIERARCHY interface type is used as the type of a handle in a command when the
+handle is required to be one of the hierarchy selectors.
+Table 46 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY Type
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Storage hierarchy
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
++TPM_RH_NULL
+
+no hierarchy
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.12 TPMI_RH_ENABLES
+The TPMI_RH_ENABLES interface type is used as the type of a handle in a command when the handle
+is required to be one of the hierarchy or NV enables.
+Table 47 — Definition of (TPM_HANDLE) TPMI_RH_ENABLES Type
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Storage hierarchy
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
+TPM_RH_PLATFORM_NV
+
+Platform NV
+
++TPM_RH_NULL
+
+no hierarchy
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 73
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.13 TPMI_RH_HIERARCHY_AUTH
+This interface type is used as the type of a handle in a command when the handle is required to be one of
+the hierarchy selectors or the Lockout Authorization.
+Table 48 — Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_AUTH Type <IN>
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Storage hierarchy
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
+TPM_RH_LOCKOUT
+
+Lockout Authorization
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.14 TPMI_RH_PLATFORM
+The TPMI_RH_PLATFORM interface type is used as the type of a handle in a command when the only
+allowed handle is TPM_RH_PLATFORM indicating that platformAuth is required.
+Table 49 — Definition of (TPM_HANDLE) TPMI_RH_PLATFORM Type <IN>
+Values
+
+Comments
+
+TPM_RH_PLATFORM
+
+Platform hierarchy
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.15 TPMI_RH_OWNER
+This interface type is used as the type of a handle in a command when the only allowed handle is
+TPM_RH_OWNER indicating that ownerAuth is required.
+Table 50 — Definition of (TPM_HANDLE) TPMI_RH_OWNER Type <IN>
+Values
+
+Comments
+
+TPM_RH_OWNER
+
+Owner hierarchy
+
++TPM_RH_NULL
+
+may allow the null handle
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+Page 74
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.16 TPMI_RH_ENDORSEMENT
+This interface type is used as the type of a handle in a command when the only allowed handle is
+TPM_RH_ENDORSEMENT indicating that endorsementAuth is required.
+Table 51 — Definition of (TPM_HANDLE) TPMI_RH_ENDORSEMENT Type <IN>
+Values
+
+Comments
+
+TPM_RH_ENDORSEMENT
+
+Endorsement hierarchy
+
++TPM_RH_NULL
+
+may allow the null handle
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.17 TPMI_RH_PROVISION
+The TPMI_RH_PROVISION interface type is used as the type of the handle in a command when the only
+allowed handles are either TPM_RH_OWNER or TPM_RH_PLATFORM indicating that either
+platformAuth or ownerAuth are allowed.
+In most cases, either platformAuth or ownerAuth may be used to authorize the commands used for
+management of the resources of the TPM and this interface type will be used.
+Table 52 — Definition of (TPM_HANDLE) TPMI_RH_PROVISION Type <IN>
+Value
+
+Comments
+
+TPM_RH_OWNER
+
+handle for ownerAuth
+
+TPM_RH_PLATFORM
+
+handle for platformAuth
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.18 TPMI_RH_CLEAR
+The TPMI_RH_CLEAR interface type is used as the type of the handle in a command when the only
+allowed handles are either TPM_RH_LOCKOUT or TPM_RH_PLATFORM indicating that either
+platformAuth or lockoutAuth are allowed.
+This interface type is normally used for performing or controlling TPM2_Clear().
+Table 53 — Definition of (TPM_HANDLE) TPMI_RH_CLEAR Type <IN>
+Value
+
+Comments
+
+TPM_RH_LOCKOUT
+
+handle for lockoutAuth
+
+TPM_RH_PLATFORM
+
+handle for platformAuth
+
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 75
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.19 TPMI_RH_NV_AUTH
+This interface type is used to identify the source of the authorization for access to an NV location. The
+handle value of a TPMI_RH_NV_AUTH shall indicate that the authorization value is either platformAuth,
+ownerAuth, or the authValue. This type is used in the commands that access an NV Index (commands of
+the form TPM2_NV_xxx) other than TPM2_NV_DefineSpace() and TPM2_NV_UndefineSpace().
+Table 54 — Definition of (TPM_HANDLE) TPMI_RH_NV_AUTH Type <IN>
+Value
+
+Comments
+
+TPM_RH_PLATFORM
+
+platformAuth is allowed
+
+TPM_RH_OWNER
+
+ownerAuth is allowed
+
+{NV_INDEX_FIRST:NV_INDEX_LAST}
+
+range for NV locations
+
+#TPM_RC_VALUE
+
+response code returned when unmarshaling of this type fails
+
+9.20 TPMI_RH_LOCKOUT
+The TPMI_RH_LOCKOUT interface type is used as the type of a handle in a command when the only
+allowed handle is TPM_RH_LOCKOUT indicating that lockoutAuth is required.
+Table 55 — Definition of (TPM_HANDLE) TPMI_RH_LOCKOUT Type <IN>
+Value
+
+Comments
+
+TPM_RH_LOCKOUT
+#TPM_RC_VALUE
+
+response code returned when the unmarshaling of this type fails
+
+9.21 TPMI_RH_NV_INDEX
+This interface type is used to identify an NV location. This type is used in the NV commands.
+Table 56 — Definition of (TPM_HANDLE) TPMI_RH_NV_INDEX Type <IN/OUT>
+Value
+
+Comments
+
+{NV_INDEX_FIRST:NV_INDEX_LAST}
+
+Range of NV Indexes
+
+#TPM_RC_VALUE
+
+error returned if the handle is out of range
+
+Page 76
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.22 TPMI_ALG_HASH
+A TPMI_ALG_HASH is an interface type of all the hash algorithms implemented on a specific TPM. Table
+57 is a list of the hash algorithms that have an algorithm ID assigned by the TCG and does not indicate
+the algorithms that will be accepted by a TPM.
+NOTE
+
+An implementation would modify this table according to the implemented algorithms, changing the values
+that are accepted as hash algorithms.
+
+Table 57 — Definition of (TPM_ALG_ID) TPMI_ALG_HASH Type
+Values
+
+Comments
+
+TPM_ALG_SHA1
+
+example
+
+TPM_ALG_SHA256
+
+example
+
+TPM_ALG_SM3_256
+
+example
+
+TPM_ALG_SHA384
+
+example
+
+TPM_ALG_SHA512
+
+example
+
++TPM_ALG_NULL
+#TPM_RC_HASH
+
+9.23 TPMI_ALG_ASYM (Asymmetric Algorithms)
+A TPMI_ALG_ASYM is an interface type of all the asymmetric algorithms implemented on a specific TPM.
+Table 58 lists each of the asymmetric algorithms that have an algorithm ID assigned by the TCG.
+Table 58 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM Type
+Values
+
+Comments
+
+TPM_ALG_RSA
+TPM_ALG_ECC
++TPM_ALG_NULL
+#TPM_RC_ASYMMETRIC
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 77
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.24 TPMI_ALG_SYM (Symmetric Algorithms)
+A TPMI_ALG_SYM is an interface type of all the symmetric algorithms that have an algorithm ID assigned
+by the TCG and are implemented on the TPM.
+The list in the table below is illustrative and will change according to the implementation. The validation
+code will only accept the subset of algorithms implemented on a TPM.
+NOTE
+
+The validation code produced by an example script will produce a CASE statement with a case for each of
+the values in the “Values” column. The case for a value is delimited by a #ifdef/#endif pair so that if the
+algorithm is not implemented on the TPM, then the case for the algorithm is not generated, and use of the
+algorithm will cause a TPM error (TPM_RC_SYMMETRIC).
+
+Table 59 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM Type
+Values
+
+Comments
+
+TPM_ALG_AES
+
+example
+
+TPM_ALG_SM4
+
+example
+
+TPM_ALG_XOR
+
+example
+
++TPM_ALG_NULL
+
+required to be present in all versions of this table
+
+#TPM_RC_SYMMETRIC
+
+9.25 TPMI_ALG_SYM_OBJECT
+A TPMI_ALG_SYM_OBJECT is an interface type of all the TCG-defined symmetric algorithms that may
+be used as companion symmetric encryption algorithm for an asymmetric object. All algorithms in this list
+shall be block ciphers usable in Cipher Feedback (CFB).
+Table 60 is illustrative. It would be modified to indicate the algorithms of the TPM.
+NOTE
+
+TPM_ALG_XOR is not allowed in this list.
+
+Table 60 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_OBJECT Type
+Values
+
+Comments
+
+TPM_ALG_AES
+
+example
+
+TPM_ALG_SM4
+
+example
+
++TPM_ALG_NULL
+
+required to be present in all versions of this table
+
+#TPM_RC_SYMMETRIC
+
+Page 78
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+9.26 TPMI_ALG_SYM_MODE
+A TPMI_ALG_SYM_MODE is an interface type of all the TCG-defined block-cipher modes of operation.
+This version of the table is not expected to be the table checked by the validation code. Rather, the table
+would be replaced by one containing the algorithms implemented on the TPM and that the values in that
+table would be checked by the input validation code.
+Table 61 — Definition of (TPM_ALG_ID) TPMI_ALG_SYM_MODE Type
+Values
+
+Comments
+
+TPM_ALG_CTR
+
+IV will be determined by use.
+If the outside provides the nonce and initial counter, then the caller can
+know what IV to provide for chaining.
+
+TPM_ALG_OFB
+
+XOR last cipher text block with last plaintext to create IV for next block
+
+TPM_ALG_CBC
+
+IV will be determined by use.
+indefinite chaining using previous output block as IV for next block
+
+TPM_ALG_CFB
+
+shall be implemented in all TPM compliant with this specification
+IV will be determined by use.
+indefinite chaining using previous cipher text as IV
+
+TPM_ALG_ECB
+
+no IV or chaining value required
+
++TPM_ALG_NULL
+#TPM_RC_MODE
+
+9.27 TPMI_ALG_KDF (Key and Mask Generation Functions)
+A TPMI_ALG_KDF is an interface type of all the key derivation functions implemented on a specific TPM.
+Table 62 is exemplary and would change based on the algorithms implemented in a TPM.
+Table 62 — Definition of (TPM_ALG_ID) TPMI_ALG_KDF Type
+Values
+
+Comments
+
+TPM_ALG_MGF1
+TPM_ALG_KDF1_SP800_108
+TPM_ALG_KDF1_SP800_56a
+TPM_ALG_KDF2
++TPM_ALG_NULL
+#TPM_RC_KDF
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 79
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+9.28 TPMI_ALG_SIG_SCHEME
+This is the definition of the interface type for a signature scheme. This table would change according to
+the algorithms implemented on the TPM.
+Table 63 — Definition of (TPM_ALG_ID) TPMI_ALG_SIG_SCHEME Type
+Values
+
+Comments
+
+TPM_ALG_RSASSA
+
+requires that RSA be implemented
+
+TPM_ALG_RSAPSS
+
+requires that RSA be implemented
+
+TPM_ALG_ECDSA
+
+requires that ECC be implemented
+
+TPM_ALG_ECDAA
+
+requires that ECC and ECDAA be implemented
+
+TPM_ALG_ECSCHNORR
+TPM_ALG_SM2
+
+requires that ECC be implemented
+
+TPM_ALG_HMAC
+
+present on all TPM
+
++TPM_ALG_NULL
+#TPM_RC_SCHEME
+
+response code when a signature scheme is not correct
+
+9.29 TPMI_ECC_KEY_EXCHANGE
+This is the definition of the interface type for an ECC key exchange scheme. This table would change
+according to the algorithms implemented on the TPM.
+Table 64 — Definition of (TPM_ALG_ID) TPMI_ECC_KEY_EXCHANGE Type
+Values
+
+Comments
+
+TPM_ALG_ECDH
+
+used for single and two phase key exchange
+
+TPM_ALG_ECMQV
+TPM_ALG_SM2
+
+requires that ECC be implemented
+
++TPM_ALG_NULL
+#TPM_RC_SCHEME
+
+response code when a key exchange scheme is not correct
+
+9.30 TPMI_ST_COMMAND_TAG
+This interface type is used for the command tags.
+The response code for a bad command tag has the same value as the TPM 1.2 response code
+(TPM_BAD_TAG). This value is used in case the software is not compatible with this specification and an
+unexpected response code might have unexpected side effects.
+Table 65 — Definition of (TPM_ST) TPMI_ST_COMMAND_TAG Type
+Values
+
+Comments
+
+TPM_ST_NO_SESSIONS
+TPM_ST_SESSIONS
+#TPM_RC_BAD_TAG
+
+Page 80
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10 Structure Definitions
+10.1 TPMS_ALGORITHM_DESCRIPTION
+This structure is a return value for a TPM2_GetCapability() that reads the installed algorithms.
+Table 66 — Definition of TPMS_ALGORITHM_DESCRIPTION Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+alg
+
+TPM_ALG_ID
+
+an algorithm
+
+attributes
+
+TPMA_ALGORITHM
+
+the attributes of the algorithm
+
+10.2 Hash/Digest Structures
+10.2.1 TPMU_HA (Hash)
+A TPMU_HA is a union of all the hash algorithms implemented on a TPM. Table 67 is exemplary and
+would change based on the algorithms implemented in a TPM.
+NOTE
+
+If processed by an automated tool, each entry of the table should be qualified (with #ifdef/#endif) so that if
+the hash algorithm is not implemented on the TPM, the parameter associated with that hash is not
+present. This will keep the union from being larger than the largest digest of a hash implemented on that
+TPM.
+
+Table 67 — Definition of TPMU_HA Union <IN/OUT, S>
+Parameter
+
+Type
+
+Selector
+
+sha1 [SHA1_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA1
+
+sha256 [SHA256_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA256
+
+sm3_256 [SM3_256_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SM3_256
+
+sha384 [SHA384_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA384
+
+sha512 [SHA512_DIGEST_SIZE]
+
+BYTE
+
+TPM_ALG_SHA512
+
+null
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Description
+
+TPM_ALG_NULL
+
+Published
+Copyright © TCG 2006-2013
+
+Page 81
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.2.2 TPMT_HA
+Table 68 shows the basic hash-agile structure used in this specification. To handle hash agility, this
+structure uses the hashAlg parameter to indicate the algorithm used to compute the digest and, by
+implication, the size of the digest.
+When transmitted, only the number of octets indicated by hashAlg is sent.
+NOTE
+
+In the exemplary code, when a TPMT_HA is allocated, the digest field is large enough to support the
+largest hash algorithm in the TPMU_HA union.
+
+Table 68 — Definition of TPMT_HA Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+selector of the hash contained in the digest that implies the
+size of the digest
+NOTE
+
+[hashAlg] digest
+
+TPMU_HA
+
+The leading “+” on the type indicates that this structure
+should pass an indication to the unmarshaling function for
+TPMI_ALG_HASH so that TPM_ALG_NULL will be
+allowed if a use of a TPMT_HA allows TPM_ALG_NULL.
+
+the digest data
+
+10.3 Sized Buffers
+10.3.1 Introduction
+The “TPM2B_” prefix is used for a structure that has a size field followed by a data buffer with the
+indicated number of octets. The size field is 16 bits.
+When the type of the second parameter in a TPM2B_ structure is BYTE, the TPM shall unmarshal the
+indicated number of octets, which may be zero.
+When the type of the second parameter in the TPM2B_ structure is not BYTE, the value of the size field
+shall either be zero indicating that no structure is to be unmarshaled; or it shall be identical to the number
+of octets unmarshaled for the second parameter.
+NOTE 1
+
+If the TPM2B_ defines a structure and not an array of octets, then the structure is self-describing and the
+TPM will be able to determine how many octets are in the structure when it is unmarshaled. If that number
+of octets is not equal to the size parameter, then it is an error.
+
+NOTE 2
+
+The reason that a structure may be put into a TPM2B_ is that the parts of the structure may be handled
+as separate opaque blocks by the application/system software. Rather than require that all of the
+structures in a command or response be marshaled or unmarshaled sequentially, the size field allows the
+structure to be manipulated as an opaque block. Placing a structure in a TPM2B_ also makes it possible
+to use parameter encryption on the structure.
+
+If a TPM2B_ is encrypted, the TPM will encrypt/decrypt the data field of the TPM2B_ but not the size
+parameter. The TPM will encrypt/decrypt the number of octets indicated by the size field.
+NOTE 3
+
+In the reference implementation, a TPM2B type is defined that is a 16-bit size field followed by a single
+byte of data. The TPM2B_ is then defined as a union that contains a TPM2B (union member ‘b’) and the
+structure in the definition table (union member ‘t’). This union is used for internally generated structures
+so that there is a way to define a structure of the correct size (forced by the ‘t’ member) while giving a way
+to pass the structure generically as a ‘b’. Most function calls use the 't' member so that the compiler will
+generate a warning if there is a type error (a TPM2B_ of the wrong type). Having the type checked helps
+avoid many issues with buffer overflow caused by a too small buffer being passed to a function.
+
+Page 82
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.3.2 TPM2B_DIGEST
+This structure is used for a sized buffer that cannot be larger than the largest digest produced by any
+hash algorithm implemented on the TPM.
+As with all sized buffers, the size is checked to see if it is within the prescribed range. If not, the response
+code is TPM_RC_SIZE.
+NOTE
+
+For any structure, like the one below, that contains an implied size check, it is implied that TPM_RC_SIZE
+is a possible response code and the response code will not be listed in the table.
+
+Table 69 — Definition of TPM2B_DIGEST Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size in octets of the buffer field; may be 0
+
+buffer[size]{:sizeof(TPMU_HA)}
+
+BYTE
+
+the buffer area that can be no larger than a digest
+
+10.3.3 TPM2B_DATA
+This structure is used for a data buffer that is required to be no larger than the size of the Name of an
+object. This size limit includes the algorithm ID of the hash and the hash data.
+Table 70 — Definition of TPM2B_DATA Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size in octets of the buffer field; may be 0
+
+buffer[size]{:sizeof(TPMT_HA)}
+
+BYTE
+
+the buffer area that contains the algorithm ID and the
+digest
+
+10.3.4 TPM2B_NONCE
+Table 71 — Definition of Types for TPM2B_NONCE
+Type
+
+Name
+
+Description
+
+TPM2B_DIGEST
+
+TPM2B_NONCE
+
+size limited to the same as the digest structure
+
+10.3.5 TPM2B_AUTH
+This structure is used for an authorization value and limits an authValue to being no larger than the
+largest digest produced by a TPM. In order to ensure consistency within an object, the authValue may be
+no larger than the size of the digest produced by the object’s nameAlg. This ensures that any TPM that
+can load the object will be able to handle the authValue of the object.
+Table 72 — Definition of Types for TPM2B_AUTH
+Type
+
+Name
+
+Description
+
+TPM2B_DIGEST
+
+TPM2B_AUTH
+
+size limited to the same as the digest structure
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 83
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.3.6 TPM2B_OPERAND
+This type is a sized buffer that can hold an operand for a comparison with an NV Index location. The
+maximum size of the operand is implementation dependent but a TPM is required to support an operand
+size that is at least as big as the digest produced by any of the hash algorithms implemented on the TPM.
+Table 73 — Definition of Types for TPM2B_OPERAND
+Type
+
+Name
+
+Description
+
+TPM2B_DIGEST
+
+TPM2B_OPERAND
+
+size limited to the same as the digest structure
+
+10.3.7 TPM2B_EVENT
+This type is a sized buffer that can hold event data.
+Table 74 — Definition of TPM2B_EVENT Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the operand buffer
+
+buffer [size] {:1024}
+
+BYTE
+
+the operand
+
+10.3.8 TPM2B_MAX_BUFFER
+This type is a sized buffer that can hold a maximally sized buffer for commands that use a large data
+buffer
+such
+as
+TPM2_PCR_Event(),
+TPM2_Hash(),
+TPM2_SequenceUpdate(),
+or
+TPM2_FieldUpgradeData().
+NOTE
+
+The above list is not comprehensive and other commands may use this buffer type.
+
+Table 75 — Definition of TPM2B_MAX_BUFFER Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the buffer
+
+buffer [size] {:MAX_DIGEST_BUFFER}
+
+BYTE
+
+the operand
+NOTE
+MAX_DIGEST_BUFFER
+is
+TPMdependent but is required to be at least 1,024.
+
+10.3.9 TPM2B_MAX_NV_BUFFER
+This type is a sized buffer that can hold a maximally sized buffer for NV data commands such as
+TPM2_NV_Read(), TPM2_NV_Write(), and TPM2_NV_Certify().
+Table 76 — Definition of TPM2B_MAX_NV_BUFFER Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the buffer
+
+buffer [size] {:MAX_NV_BUFFER_SIZE}
+
+BYTE
+
+the operand
+NOTE
+MAX_NV_BUFFER_SIZE
+dependent
+
+Page 84
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+is
+
+TPM-
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.3.10 TPM2B_TIMEOUT
+This TPM-dependent structure is used to provide the timeout value for an authorization.
+Table 77 — Definition of TPM2B_TIMEOUT Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the timeout value
+This value is fixed for a TPM implementation.
+
+buffer [size] {:sizeof(UINT64)}
+
+BYTE
+
+the timeout value
+
+10.3.11 TPM2B_IV
+This structure is used for passing an initial value for a symmetric block cipher to or from the TPM. The
+size is set to be the largest block size of any implemented symmetric cipher implemented on the TPM.
+Table 78 — Definition of TPM2B_IV Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the timeout value
+This value is fixed for a TPM implementation.
+
+buffer [size] {:MAX_SYM_BLOCK_SIZE}
+
+BYTE
+
+the timeout value
+
+10.4 Names
+10.4.1 Introduction
+The Name of an entity is used in place of the handle in authorization computations. The substitution
+occurs in cpHash and policyHash computations.
+For an entity that is defined by a public area (objects and NV Indexes), the Name is the hash of the public
+structure that defines the entity. The hash is done using the nameAlg of the entity.
+NOTE
+
+For an object, a TPMT_PUBLIC defines the entity. For an NV Index, a TPMS_NV_PUBLIC defines the
+entity.
+
+For entities not defined by a public area, the Name is the handle that is used to refer to the entity.
+10.4.2 TPMU_NAME
+Table 79 — Definition of TPMU_NAME Union <>
+Parameter
+
+Type
+
+digest
+
+TPMT_HA
+
+when the Name is a digest
+
+handle
+
+TPM_HANDLE
+
+when the Name is a handle
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Selector
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Page 85
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.4.3 TPM2B_NAME
+This buffer holds a Name for any entity type.
+The type of Name in the structure is determined by context and the size parameter. If size is four, then
+the Name is a handle. If size is zero, then no Name is present. Otherwise, the size shall be the size of a
+TPM_ALG_ID plus the size of the digest produced by the indicated hash algorithm.
+Table 80 — Definition of TPM2B_NAME Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the Name structure
+
+name[size]{:sizeof(TPMU_NAME)}
+
+BYTE
+
+the Name structure
+
+10.5 PCR Structures
+10.5.1 TPMS_PCR_SELECT
+This structure provides a standard method of specifying a list of PCR.
+PCR numbering starts at zero.
+PcrSelect is an array of octets. The octet containing the bit corresponding to a specific PCR is found by
+dividing the PCR number by 8.
+EXAMPLE 1
+
+The bit in pcrSelect corresponding to PCR 19 is in pcrSelect [2] (19/8 = 2).
+
+The least significant bit in a octet is bit number 0. The bit in the octet associated with a PCR is the
+remainder after division by 8.
+EXAMPLE 2
+
+The bit in pcrSelect [2] corresponding to PCR 19 is bit 3 (19 mod 8). If sizeofSelect is 3, then the
+pcrSelect array that would specify PCR 19 and no other PCR is 00 00 08 16.
+
+Each bit in pcrSelect indicates whether the corresponding PCR is selected (1) or not (0). If the pcrSelect
+is all zero bits, then no PCR is selected.
+SizeofSelect indicates the number of octets in pcrSelect. The allowable values for sizeofSelect is
+determined by the number of PCR required by the applicable platform-specific specification and the
+number of PCR implemented in the TPM. The minimum value for sizeofSelect is:
+PCR_SELECT_MIN ≔ (PLATFORM_PCR + 7) / 8
+
+(1)
+
+where
+PLATFORM_PCR
+
+the number of PCR required by the platform-specific specification
+
+The maximum value for sizeofSelect is:
+PCR_SELECT_MAX ≔ (IMPLEMENTATION_PCR + 7) / 8
+
+(2)
+
+where
+IMPLEMENTATION_PCR
+
+Page 86
+October 31, 2013
+
+the number of PCR implemented on the TPM
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+If the TPM implements more PCR than there are bits in pcrSelect, the additional PCR are not selected.
+EXAMPLE 3
+
+If the applicable platform-specific specification requires that the TPM have a minimum of 24 PCR but the
+TPM implements 32, then a PCR select of 3 octets would imply that PCR 24-31 are not selected.
+
+Table 81 — Definition of TPMS_PCR_SELECT Structure
+Parameter
+
+Type
+
+Description
+
+sizeofSelect {PCR_SELECT_MIN:}
+
+UINT8
+
+the size in octets of the pcrSelect array
+
+pcrSelect [sizeofSelect] {:PCR_SELECT_MAX}
+
+BYTE
+
+the bit map of selected PCR
+
+#TPM_RC_VALUE
+
+10.5.2 TPMS_PCR_SELECTION
+Table 82 — Definition of TPMS_PCR_SELECTION Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm associated with the
+selection
+
+sizeofSelect {PCR_SELECT_MIN:}
+
+UINT8
+
+the size in octets of the pcrSelect array
+
+pcrSelect [sizeofSelect] {:PCR_SELECT_MAX}
+
+BYTE
+
+the bit map of selected PCR
+
+#TPM_RC_VALUE
+
+10.6 Tickets
+10.6.1 Introduction
+Tickets are evidence that the TPM has previously processed some information. A ticket is an HMAC over
+the data using a secret key known only to the TPM. A ticket is a way to expand the state memory of the
+TPM. A ticket is only usable by the TPM that produced it.
+The formulations for tickets shown in this clause are to be used by a TPM that is compliant with this
+specification.
+The method of creating the ticket data is:
+
+HMACcontexAlg(proof, (ticketType || param { || param {…}))
+
+(3)
+
+where
+
+HMACcontexAlg()
+
+an HMAC using the hash used for context integrity
+
+proof
+
+a TPM secret value (depends on hierarchy)
+
+ticketType
+
+a value to differentiate the tickets
+
+param
+
+one or more values that were checked by the TPM
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 87
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+The proof value used for each hierarchy is shown in Table 83.
+Table 83 — Values for proof Used in Tickets
+Hierarchy
+
+proof
+
+Description
+
+None
+
+Empty Buffer
+
+Platform
+
+phProof
+
+a value that changes with each change of the PPS
+
+Owner
+
+shProof
+
+a value that changes with each change of the SPS
+
+Endorsement
+
+ehProof
+
+a value that changes with each change of either the EPS or SPS
+
+The format for a ticket is shown in Table 84. This is a template for the tickets shown in the remainder of
+this clause.
+Table 84 — General Format of a Ticket
+Parameter
+
+Type
+
+Description
+
+tag
+
+TPM_ST
+
+structure tag indicating the type of the ticket
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy of the proof value
+
+digest
+
+TPM2B_DIGEST
+
+the HMAC over the ticket-specific data
+
+10.6.2 A NULL Ticket
+When a command requires a ticket and no ticket is available, the caller is required to provide a structure
+with a ticket tag that is correct for the context. The hierarchy shall be set to TPM_RH_NULL, and digest
+shall be the Empty Buffer (a buffer with a size field of zero). This construct is the NULL Ticket. When a
+response indicates that a ticket is returned, the TPM may return a NULL Ticket.
+NOTE
+
+Because each use of a ticket requires that the structure tag for the ticket be appropriate for the use, t here
+is no single representation of a NULL Ticket that will work in all circumstances. Minimally, a NULL ticket
+will have a structure type that is appropriate for the context.
+
+Page 88
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.6.3 TPMT_TK_CREATION
+This ticket is produced by TPM2_Create() or TPM2_CreatePrimary(). It is used to bind the creation data
+to the object to which it applies. The ticket is computed by
+
+HMACcontextAlg(proof, (TPM_ST_CREATION || name || HnameAlg(TPMS_CREATION_DATA)))
+
+(4)
+
+where
+
+HMACcontextAlg()
+
+an HMAC using the context integrity hash algorithm
+
+proof
+
+a TPM secret value associated with the hierarchy associated with name
+
+TPM_ST_CREATION
+
+a value used to ensure that the ticket is properly used
+
+name
+
+the Name of the object to which the creation data is to be associated
+
+HnameAlg()
+
+hash using the nameAlg of the created object
+
+TPMS_CREATION_DATA the creation data structure associated with name
+Table 85 — Definition of TPMT_TK_CREATION Structure
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_CREATION}
+
+TPM_ST
+
+ticket structure tag
+error returned when tag is not TPM_ST_CREATION
+
+#TPM_RC_TAG
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy containing name
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC produced using a proof value
+of hierarchy.
+
+EXAMPLE
+
+A NULL Creation Ticket is the tuple <TPM_ST_CREATION, TPM_RH_NULL, 0x0000>.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 89
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.6.4 TPMT_TK_VERIFIED
+This ticket is produced by TPM2_VerifySignature(). This formulation is used for multiple ticket uses. The
+ticket provides evidence that the TPM has validated that a digest was signed by a key with the Name of
+keyName. The ticket is computed by
+
+HMACcontextAlg(proof, (TPM_ST_VERIFIED || digest || keyName))
+
+(5)
+
+where
+
+HMACcontextAlg()
+
+an HMAC using the context integrity hash
+
+proof
+
+a TPM secret value associated with the hierarchy associated with
+
+TPM_ST_VERIFIED
+
+a value used to ensure that the ticket is properly used
+
+digest
+
+the signed digest
+
+keyName
+
+Name of the key that signed digest
+
+keyName
+
+Table 86 — Definition of TPMT_TK_VERIFIED Structure
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_VERIFIED}
+
+TPM_ST
+
+ticket structure tag
+error returned when tag is not TPM_ST_VERIFIED
+
+#TPM_RC_TAG
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy containing keyName
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC produced using a proof value
+of hierarchy.
+
+EXAMPLE
+
+A NULL Verified Ticket is the tuple <TPM_ST_VERIFIED, TPM_RH_NULL, 0x0000>.
+
+Page 90
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.6.5 TPMT_TK_AUTH
+This ticket is produced by TPM2_PolicySigned() and TPM2_PolicySecret() when the authorization has an
+expiration time. The ticket is computed by
+
+HMACcontextAlg(proof, (TPM_ST_AUTH_xxx || timeout || cpHash || policyRef || keyName))
+
+(6)
+
+where
+
+HMACcontextAlg()
+
+an HMAC using the context integrity hash
+
+proof
+
+a TPM secret value associated with the hierarchy of the key associated
+with keyName
+
+TPM_ST_AUTH_xxx
+
+either TPM_ST_AUTH_SIGNED or TPM_ST_AUTH_SECRET; used to
+ensure that the ticket is properly used
+
+timeout
+
+implementation-specific value indicating when the authorization expires
+
+cpHash
+
+optional hash of the authorized command
+
+policyRef
+
+optional reference to a policy value
+
+keyName
+
+Name of the key that signed the authorization
+Table 87 — Definition of TPMT_TK_AUTH Structure
+
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_AUTH_SIGNED, TPM_ST_AUTH_SECRET} TPM_ST
+
+ticket structure tag
+
+#TPM_RC_TAG
+
+error returned when tag is
+not TPM_ST_AUTH
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy of the object
+used to produce the ticket
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC
+produced using a proof
+value of hierarchy.
+
+EXAMPLE
+
+A NULL Auth Ticket is the tuple <TPM_ST_AUTH_SIGNED, TPM_RH_NULL, 0x0000> or the tuple
+<TPM_ST_AUTH_SIGNED, TPM_RH_NULL, 0x0000>
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 91
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.6.6 TPMT_TK_HASHCHECK
+This ticket is produced by TPM2_SequenceComplete() when the message that was digested did not start
+with TPM_GENERATED_VALUE. The ticket is computed by
+
+HMACcontexAlg(proof, (TPM_ST_HASHCHECK || digest))
+
+(7)
+
+where
+
+HMACcontexAlg ()
+
+an HMAC using the context integrity hash
+
+proof
+
+a TPM secret value associated with the hierarchy indicated by the
+command
+
+TPM_ST_HASHCHECK
+
+a value used to ensure that the ticket is properly used
+
+digest
+
+the digest of the data
+Table 88 — Definition of TPMT_TK_HASHCHECK Structure
+
+Parameter
+
+Type
+
+Description
+
+tag {TPM_ST_HASHCHECK}
+
+TPM_ST
+
+ticket structure tag
+
+#TPM_RC_TAG
+
+error returned when is not TPM_ST_HASHCHECK
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy
+
+digest
+
+TPM2B_DIGEST
+
+This shall be the HMAC produced using a proof value
+of hierarchy.
+
+10.7 Property Structures
+10.7.1 TPMS_ALG_PROPERTY
+This structure is used to report the properties of an algorithm identifier. It is returned in response to a
+TPM2_GetCapability() with capability = TPM_CAP_ALG.
+Table 89 — Definition of TPMS_ALG_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+alg
+
+TPM_ALG_ID
+
+an algorithm identifier
+
+algProperties
+
+TPMA_ALGORITHM
+
+the attributes of the algorithm
+
+10.7.2 TPMS_TAGGED_PROPERTY
+This structure is used to report the properties that are UINT32 values. It is returned in response to a
+TPM2_GetCapability().
+Table 90 — Definition of TPMS_TAGGED_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+property
+
+TPM_PT
+
+a property identifier
+
+value
+
+UINT32
+
+the value of the property
+
+Page 92
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.7.3 TPMS_TAGGED_PCR_SELECT
+This structure is used in TPM2_GetCapability() to return the attributes of the PCR.
+Table 91 — Definition of TPMS_TAGGED_PCR_SELECT Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+tag
+
+TPM_PT
+
+the property identifier
+
+sizeofSelect {PCR_SELECT_MIN:}
+
+UINT8
+
+the size in octets of the pcrSelect array
+
+pcrSelect [sizeofSelect] {:PCR_SELECT_MAX}
+
+BYTE
+
+the bit map of PCR with the identified property
+
+10.8 Lists
+10.8.1 TPML_CC
+A list of command codes may be input to the TPM or returned by the TPM depending on the command.
+Table 92 — Definition of TPML_CC Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of commands in the commandCode list;
+may be 0
+
+commandCodes[count]{:MAX_CAP_CC}
+
+TPM_CC
+
+a list of command codes
+The maximum only applies to a command code
+list in a command. The response size is limited
+only by the size of the parameter buffer.
+
+#TPM_RC_SIZE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+response code when count is greater than the
+maximum allowed list size
+
+Published
+Copyright © TCG 2006-2013
+
+Page 93
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.8.2 TPML_CCA
+This list is only used in TPM2_GetCapability(capability = TPM_CAP_COMMANDS).
+The values in the list are returned in commandIndex order with vendor-specific commands returned after
+other commands. Because of the other attributes, the commands may not be returned in strict numerical
+order. They will be in commandIndex order.
+Table 93 — Definition of TPML_CCA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of values in the commandAttributes list;
+may be 0
+
+commandAttributes[count]{:MAX_CAP_CC}
+
+TPMA_CC
+
+a list of command codes attributes
+
+10.8.3 TPML_ALG
+This list is returned by TPM2_IncrementalSelfTest().
+Table 94 — Definition of TPML_ALG Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of algorithms in the algorithms list; may be 0
+
+algorithms[count]{:MAX_ALG_LIST_SIZE}
+
+TPM_ALG_ID
+
+ a list of algorithm IDs
+The maximum only applies to an algorithm list in a
+command. The response size is limited only by the
+size of the parameter buffer.
+response code when count is greater than the
+maximum allowed list size
+
+#TPM_RC_SIZE
+
+10.8.4 TPML_HANDLE
+This structure is used when the TPM returns a list of loaded handles when the capability in
+TPM2_GetCapability() is TPM_CAP_HANDLE.
+NOTE
+
+This list is not used as input to the TPM.
+
+Table 95 — Definition of TPML_HANDLE Structure <OUT>
+Name
+
+Type
+
+Description
+
+count
+
+UINT32
+
+the number of handles in the list
+may have a value of 0
+
+handle[count]{: MAX_CAP_HANDLES}
+
+TPM_HANDLE
+
+an array of handles
+
+#TPM_RC_SIZE
+
+Page 94
+October 31, 2013
+
+response code when count is greater than the
+maximum allowed list size
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.8.5 TPML_DIGEST
+This list is used to convey a list of digest values. This type is used in TPM2_PolicyOR() and in
+TPM2_PCR_Read().
+Table 96 — Definition of TPML_DIGEST Structure
+Parameter
+
+Type
+
+Description
+
+count {2:}
+
+UINT32
+
+number of digests in the list, minimum is two for
+TPM2_PolicyOR().
+
+digests[count]{:8}
+
+TPM2B_DIGEST
+
+ a list of digests
+For TPM2_PolicyOR(), all digests will have been
+computed using the digest of the policy session. For
+TPM2_PCR_Read(), each digest will be the size of the
+digest for the bank containing the PCR.
+
+#TPM_RC_SIZE
+
+response code when count is not at least two or is
+greater than eight
+
+10.8.6 TPML_DIGEST_VALUES
+This list is used to convey a list of digest values. This type is returned by TPM2_Event() and
+TPM2_SequenceComplete() and is an input for TPM2_PCR_Extend().
+NOTE 1
+
+This construct limits the number of hashes in the list to the number of digests implemented in the TPM
+rather than the number of PCR banks. This allows extra values to appear in a call t o
+TPM2_PCR_Extend().
+
+NOTE 2
+
+The digest for an unimplemented hash algorithm may not be in a list because the TPM may not recognize
+the algorithm as being a hash and it may not know the digest size.
+
+Table 97 — Definition of TPML_DIGEST_VALUES Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of digests in the list
+
+digests[count]{:HASH_COUNT}
+
+TPMT_HA
+
+a list of tagged digests
+response code when count is greater than the possible
+number of banks
+
+#TPM_RC_SIZE
+
+10.8.7 TPM2B_DIGEST_VALUES
+Digest list in a sized buffer. This list is returned by TPM2_PCR_SequenceComplete().
+Table 98 — Definition of TPM2B_DIGEST_VALUES Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the operand buffer
+
+buffer [size] {:sizeof(TPML_DIGEST_VALUES)}
+
+BYTE
+
+the operand
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 95
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.8.8 TPML_PCR_SELECTION
+This list is used to indicate the PCR that are included in a selection when more than one PCR value may
+be selected.
+This structure is an input parameter to TPM2_PolicyPCR() to indicate the PCR that will be included in the
+digest of PCR for the authorization. The structure is used in TPM2_PCR_Read() command to indicate the
+PCR values to be returned and in the response to indicate which PCR are included in the list of returned
+digests. The structure is an output parameter from TPM2_Create() and indicates the PCR used in the
+digest of the PCR state when the object was created. The structure is also contained in the attestation
+structure of TPM2_Quote().
+When this structure is used to select PCR to be included in a digest, the selected PCR are concatenated
+to create a “message” containing all of the PCR, and then the message is hashed using the contextspecific hash algorithm.
+Table 99 — Definition of TPML_PCR_SELECTION Structure
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of selection structures
+A value of zero is allowed.
+
+pcrSelections[count]{:HASH_COUNT}
+
+TPMS_PCR_SELECTION
+
+list of selections
+response code when count is greater
+than the possible number of banks
+
+#TPM_RC_SIZE
+
+10.8.9 TPML_ALG_PROPERTY
+This list is used to report on a list of algorithm attributes. It is returned in a TPM2_GetCapability().
+Table 100 — Definition of TPML_ALG_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of algorithm properties structures
+A value of zero is allowed.
+
+algProperties[count]{:MAX_CAP_ALGS}
+
+TPMS_ALG_PROPERTY
+
+list of properties
+
+10.8.10 TPML_TAGGED_TPM_PROPERTY
+This list is used to report on a list of properties that are TPMS_TAGGED_PROPERTY values. It is
+returned by a TPM2_GetCapability().
+Table 101 — Definition of TPML_TAGGED_TPM_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of properties
+A value of zero is allowed.
+
+tpmProperty[count]{:MAX_TPM_PROPERTIES}
+
+TPMS_TAGGED_PROPERTY
+
+Page 96
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+an array of tagged properties
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.8.11 TPML_TAGGED_PCR_PROPERTY
+This list is used to report on a list of properties that are TPMS_PCR_SELECT values. It is returned by a
+TPM2_GetCapability().
+Table 102 — Definition of TPML_TAGGED_PCR_PROPERTY Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of properties
+A value of zero is allowed.
+
+pcrProperty[count]{:MAX_PCR_PROPERTIES}
+
+TPMS_TAGGED_PCR_SELECT
+
+ a tagged PCR selection
+
+10.8.12 TPML_ECC_CURVE
+This list is used to report the ECC curve ID values supported by the TPM. It is returned by a
+TPM2_GetCapability().
+Table 103 — Definition of {ECC} TPML_ECC_CURVE Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+count
+
+UINT32
+
+number of curves
+A value of zero is allowed.
+
+eccCurves[count]{:MAX_ECC_CURVES}
+
+TPM_ECC_CURVE
+
+array of ECC curve identifiers
+
+10.9 Capabilities Structures
+10.9.1 TPMU_CAPABILITIES
+Table 104 — Definition of TPMU_CAPABILITIES Union <OUT>
+Parameter
+
+Type
+
+Selector
+
+algorithms
+
+TPML_ALG_PROPERTY
+
+TPM_CAP_ALGS
+
+handles
+
+TPML_HANDLE
+
+TPM_CAP_HANDLES
+
+command
+
+TPML_CCA
+
+TPM_CAP_COMMANDS
+
+ppCommands
+
+TPML_CC
+
+TPM_CAP_PP_COMMANDS
+
+auditCommands
+
+TPML_CC
+
+TPM_CAP_AUDIT_COMMANDS
+
+assignedPCR
+
+TPML_PCR_SELECTION
+
+TPM_CAP_PCRS
+
+tpmProperties
+
+TPML_TAGGED_TPM_PROPERTY
+
+TPM_CAP_TPM_PROPERTIES
+
+pcrProperties
+
+TPML_TAGGED_PCR_PROPERTY
+
+TPM_CAP_PCR_PROPERTIES
+
+eccCurves
+
+TPML_ECC_CURVE
+
+TPM_CAP_ECC_CURVES
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Description
+
+TPM_ALG_ECC
+
+Page 97
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.9.2 TPMS_CAPABILITY_DATA
+This data area is returned in response to a TPM2_GetCapability().
+Table 105 — Definition of TPMS_CAPABILITY_DATA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+capability
+
+TPM_CAP
+
+the capability
+
+[capability]data
+
+TPMU_CAPABILITIES
+
+the capability data
+
+10.10 Clock/Counter Structures
+10.10.1 TPMS_CLOCK_INFO
+This structure is used in each of the attestation commands.
+Table 106 — Definition of TPMS_CLOCK_INFO Structure
+Parameter
+
+Type
+
+Description
+
+clock
+
+UINT64
+
+time in milliseconds during which the TPM has been powered
+This structure element is used to report on the TPM's Clock value.
+The value of Clock shall be recorded in non-volatile memory no
+22
+less often than once per 2 milliseconds (~69.9 minutes) of TPM
+operation. The reference for the millisecond timer is the TPM
+oscillator.
+This value is reset to zero when the Storage Primary Seed is
+changed (TPM2_Clear()).
+This value may be advanced by TPM2_AdvanceClock().
+
+resetCount
+
+UINT32
+
+number of occurrences of TPM Reset since the last TPM2_Clear()
+
+restartCount
+
+UINT32
+
+number of times that TPM2_Shutdown() or _TPM_Hash_Start have
+occurred since the last TPM Reset or TPM2_Clear().
+
+safe
+
+TPMI_YES_NO
+
+no value of Clock greater than the current value of Clock has been
+previously reported by the TPM. Set to YES on TPM2_Clear().
+
+10.10.2 Clock
+Clock is a monotonically increasing counter that advances whenever power is applied to the TPM. The
+value of Clock may be set forward with TPM2_ClockSet() if ownerAuth or platformAuth is provided. The
+value of Clock is incremented each millisecond.
+TPM2_Clear() will set Clock to zero.
+Clock will be non-volatile but may have a volatile component that is updated every millisecond with the
+non-volatile component updated at a lower rate. If the implementation uses a volatile component, the non22
+volatile component shall be updated no less frequently than every 2 milliseconds (~69.9 minutes). The
+update rate of the non-volatile portion of Clock shall be reported by a TPM2_GetCapability() with
+capability = TPM_CAP_TPM_PROPERTIES and property = TPM_PT_CLOCK_UPDATE.
+10.10.3 ResetCount
+This counter shall increment on each TPM Reset. This counter shall be reset to zero by TPM2_Clear().
+
+Page 98
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.10.4 RestartCount
+This counter shall increment by one for each TPM Restart or TPM Resume. The restartCount shall be
+reset to zero on a TPM Reset or TPM2_Clear().
+10.10.5 Safe
+This parameter is set to YES when the value reported in Clock is guaranteed to be unique for the current
+Owner. It is set to NO when the value of Clock may have been reported in a previous attestation or
+access.
+This parameter will be YES if a TPM2_Startup() was preceded by TPM2_Shutdown() with no intervening
+commands. It will also be YES after an update of the non-volatile bits of Clock have been updated at the
+end of an update interval.
+If a TPM implementation does not implement
+TPMS_CLOCK_INFO.clock shall always be zero.
+
+Clock,
+
+Safe
+
+shall
+
+always
+
+be
+
+NO
+
+and
+
+This parameter will be set to YES by TPM2_Clear().
+10.10.6 TPMS_TIME_INFO
+This structure is used in the TPM2_TICK attestation.
+The Time value reported in this structure is reset whenever the TPM is reset. An implementation may
+reset the value of Time any time after _TPM_Init and before the TPM returns after TPM2_Start(). The
+value of Time shall increment continuously while power is applied to the TPM.
+Table 107 — Definition of TPMS_TIME_INFO Structure
+Parameter
+
+Type
+
+Description
+
+time
+
+UINT64
+
+time in milliseconds since the last _TPM_Init() or TPM2_Startup()
+This structure element is used to report on the TPM's Time value.
+
+clockInfo
+
+TPMS_CLOCK_INFO
+
+a structure containing the clock information
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 99
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.11 TPM Attestation Structures
+10.11.1 Introduction
+This clause describes the structures that are used when a TPM creates a structure to be signed. The
+signing structures follow a standard format TPM2B_ATTEST with case-specific information embedded.
+10.11.2 TPMS_TIME_ATTEST_INFO
+This structure is used when the TPM performs TPM2_GetClock.
+Table 108 — Definition of TPMS_TIME_ATTEST_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+time
+
+TPMS_TIME_INFO
+
+the Time, clock, resetCount, restartCount, and Safe indicator
+
+firmwareVersion
+
+UINT64
+
+a vendor-specific value indicating the version number of the
+firmware
+
+10.11.3 TPMS_CERTIFY_INFO
+This is the attested data for TPM2_Certify().
+Table 109 — Definition of TPMS_CERTIFY_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+name
+
+TPM2B_NAME
+
+Name of the certified object
+
+qualifiedName
+
+TPM2B_NAME
+
+Qualified Name of the certified object
+
+10.11.1 TPMS_QUOTE_INFO
+This is the attested data for TPM2_Quote().
+Table 110 — Definition of TPMS_QUOTE_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+pcrSelect
+
+TPML_PCR_SELECTION
+
+information on algID, PCR selected and digest
+
+pcrDigest
+
+TPM2B_DIGEST
+
+digest of the selected PCR using the hash of the signing key
+
+Page 100
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.11.2 TPMS_COMMAND_AUDIT_INFO
+This is the attested data for TPM2_GetCommandAuditDigest().
+Table 111 — Definition of TPMS_COMMAND_AUDIT_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+auditCounter
+
+UINT64
+
+the monotonic audit counter
+
+digestAlg
+
+TPM_ALG_ID
+
+hash algorithm used for the command audit
+
+auditDigest
+
+TPM2B_DIGEST
+
+the current value of the audit digest
+
+commandDigest
+
+TPM2B_DIGEST
+
+digest of the command codes being audited using digestAlg
+
+10.11.3 TPMS_SESSION_AUDIT_INFO
+This is the attested data for TPM2_GetSessionAuditDigest().
+Table 112 — Definition of TPMS_SESSION_AUDIT_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+exclusiveSession
+
+TPMI_YES_NO
+
+current exclusive status of the session
+TRUE if all of the commands recorded in the sessionDigest were
+executed without any intervening TPM command that did not use
+this transport session
+
+sessionDigest
+
+TPM2B_DIGEST
+
+the current value of the session audit digest
+
+10.11.4 TPMS_CREATION_INFO
+This is the attested data for TPM2_CertifyCreation().
+Table 113 — Definition of TPMS_CREATION_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+objectName
+
+TPM2B_NAME
+
+Name of the object
+
+creationHash
+
+TPM2B_DIGEST
+
+creationHash
+
+10.11.5 TPMS_NV_CERTIFY_INFO
+This structure contains the Name and contents of the selected NV Index that is certified by
+TPM2_NV_Certify().
+Table 114 — Definition of TPMS_NV_CERTIFY_INFO Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+indexName
+
+TPM2B_NAME
+
+Name of the NV Index
+
+offset
+
+UINT16
+
+the offset parameter of TPM2_NV_Certify()
+
+nvContents
+
+TPM2B_MAX_NV_BUFFER
+
+contents of the NV Index
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 101
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.11.6 TPMI_ST_ATTEST
+Table 115 — Definition of (TPM_ST) TPMI_ST_ATTEST Type <OUT>
+Value
+
+Description
+
+TPM_ST_ATTEST_CERTIFY
+
+generated by TPM2_Certify()
+
+TPM_ST_ATTEST_QUOTE
+
+generated by TPM2_Quote()
+
+TPM_ST_ATTEST_SESSION_AUDIT
+
+generated by TPM2_GetSessionAuditDigest()
+
+TPM_ST_ATTEST_COMMAND_AUDIT
+
+generated by TPM2_GetCommandAuditDigest()
+
+TPM_ST_ATTEST_TIME
+
+generated by TPM2_GetTime()
+
+TPM_ST_ATTEST_CREATION
+
+generated by TPM2_CertifyCreation()
+
+TPM_ST_ATTEST_NV
+
+generated by TPM2_NV_Certify()
+
+10.11.7 TPMU_ATTEST
+Table 116 — Definition of TPMU_ATTEST Union <OUT>
+Parameter
+
+Type
+
+Selector
+
+certify
+
+TPMS_CERTIFY_INFO
+
+TPM_ST_ATTEST_CERTIFY
+
+creation
+
+TPMS_CREATION_INFO
+
+TPM_ST_ATTEST_CREATION
+
+quote
+
+TPMS_QUOTE_INFO
+
+TPM_ST_ATTEST_QUOTE
+
+commandAudit
+
+TPMS_COMMAND_AUDIT_INFO
+
+TPM_ST_ATTEST_COMMAND_AUDIT
+
+sessionAudit
+
+TPMS_SESSION_AUDIT_INFO
+
+TPM_ST_ATTEST_SESSION_AUDIT
+
+time
+
+TPMS_TIME_ATTEST_INFO
+
+TPM_ST_ATTEST_TIME
+
+nv
+
+TPMS_NV_CERTIFY_INFO
+
+TPM_ST_ATTEST_NV
+
+Page 102
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+10.11.8 TPMS_ATTEST
+This structure is used on each TPM-generated signed structure. The signature is over this structure.
+When the structure is signed by a key in the Storage hierarchy, the values of clockInfo.resetCount,
+clockInfo.restartCount, and firmwareVersion are obfuscated with a per-key obfuscation value.
+Table 117 — Definition of TPMS_ATTEST Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+magic
+
+TPM_GENERATED
+
+the indication that this structure was created by a TPM (always
+TPM_GENERATED_VALUE)
+
+type
+
+TPMI_ST_ATTEST
+
+type of the attestation structure
+
+qualifiedSigner
+
+TPM2B_NAME
+
+Qualified Name of the signing key
+
+extraData
+
+TPM2B_DATA
+
+external information supplied by caller
+NOTE
+
+A TPM2B_DATA structure provides room for a digest and a
+method indicator to indicate the components of the digest.
+The definition of this method indicator is outside the scope
+of this specification.
+
+clockInfo
+
+TPMS_CLOCK_INFO
+
+Clock, resetCount, restartCount, and Safe
+
+firmwareVersion
+
+UINT64
+
+TPM-vendor-specific field identifying the firmware on the TPM
+
+[type]attested
+
+TPMU_ATTEST
+
+the type-specific attestation information
+
+10.11.9 TPM2B_ATTEST
+This sized buffer to contain the signed structure. The attestationData is the signed portion of the structure.
+The size parameter is not signed.
+Table 118 — Definition of TPM2B_ATTEST Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the attestationData structure
+
+attestationData[size]{:sizeof(TPMS_ATTEST)}
+
+BYTE
+
+the signed structure
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 103
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+10.12 Authorization Structures
+The structures in this clause are used for all authorizations. One or more of these structures will be
+present in a command or response that has a tag of TPM_ST_SESSIONS.
+10.12.1 TPMS_AUTH_COMMAND
+This is the format used for each of the authorizations in the session area of a command.
+Table 119 — Definition of TPMS_AUTH_COMMAND Structure <IN>
+Parameter
+
+Type
+
+Description
+
+sessionHandle
+
+TPMI_SH_AUTH_SESSION+
+
+the session handle
+
+nonce
+
+TPM2B_NONCE
+
+the session nonce, may be the Empty Buffer
+
+sessionAttributes
+
+TPMA_SESSION
+
+the session attributes
+
+hmac
+
+TPM2B_AUTH
+
+either an HMAC, a password, or an EmptyAuth
+
+10.12.2 TPMS_AUTH_RESPONSE
+This is the format for each of the authorizations in the session area of the response. If the TPM returns
+TPM_RC_SUCCESS, then the session area of the response contains the same number of authorizations
+as the command and the authorizations are in the same order.
+Table 120 — Definition of TPMS_AUTH_RESPONSE Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+nonce
+
+TPM2B_NONCE
+
+the session nonce, may be the Empty Buffer
+
+sessionAttributes
+
+TPMA_SESSION
+
+the session attributes
+
+hmac
+
+TPM2B_AUTH
+
+either an HMAC, a password, or an EmptyAuth
+
+Page 104
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11 Algorithm Parameters and Structures
+11.1 Symmetric
+11.1.1 Introduction
+This clause defines the parameters and structures for describing symmetric algorithms.
+11.1.2 TPMI_AES_KEY_BITS
+This interface type defines the supported sizes for an AES key. This type is used to allow the
+unmarshaling routine to generate the proper validation code for the supported key sizes. An
+implementation that supports different key sizes would have a different set of selections.
+When used in TPM2_StartAuthSession(), the mode parameter shall be TPM_ALG_CFB.
+NOTE 1
+
+Key size is expressed in bits.
+
+NOTE 2
+
+The definition for AES_KEY_SIZES_BITS used in the reference implementation is found in Annex B
+
+Table 121 — Definition of {AES} (TPM_KEY_BITS) TPMI_AES_KEY_BITS Type
+Parameter
+
+Description
+
+$AES_KEY_SIZES_BITS
+
+number of bits in the key
+
+#TPM_RC_VALUE
+
+error when key size is not supported
+
+11.1.3 TPMI_SM4_KEY_BITS
+This interface type defines the supported sizes for an SM4 key. This type is used to allow the
+unmarshaling routine to generate the proper validation code for the supported key sizes. An
+implementation that supports different key sizes would have a different set of selections.
+NOTE
+
+SM4 only supports a key size of 128 bits.
+
+Table 122 — Definition of {SM4} (TPM_KEY_BITS) TPMI_SM4_KEY_BITS Type
+Parameter
+
+Description
+
+$SM4_KEY_SIZES_BITS
+
+number of bits in the key
+
+#TPM_RC_VALUE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 105
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.1.4 TPMU_SYM_KEY_BITS
+This union is used to collect the symmetric encryption key sizes.
+The xor entry is a hash algorithms selector and not a key size in bits. This overload is used in order to
+avoid an additional level of indirection with another union and another set of selectors.
+The xor entry is only selected in a TPMT_SYM_DEF, which is used to select the parameter encryption
+value.
+Table 123 — Definition of TPMU_SYM_KEY_BITS Union
+Parameter
+
+Type
+
+Selector
+
+aes
+
+TPMI_AES_KEY_BITS
+
+TPM_ALG_AES
+
+SM4
+
+TPMI_SM4_KEY_BITS
+
+TPM_ALG_SM4
+
+sym
+
+TPM_KEY_BITS
+
+xor
+
+TPMI_ALG_HASH
+
+Description
+
+when selector may be any of the
+symmetric block ciphers
+
+overload for using xor
+NOTE
+
+null
+
+
+11.1.5 TPMU_SYM_MODE
+This union allows the mode value in a TPMT_SYM_DEF or TPMT_SYM_DEF_OBJECT to be empty.
+Table 124 — Definition of TPMU_SYM_MODE Union
+Parameter
+
+Type
+
+Selector
+
+Description
+
+aes
+
+TPMI_ALG_SYM_MODE
+
+TPM_ALG_AES
+
+NOTE
+
+
+SM4
+
+TPMI_ALG_SYM_MODE
+
+TPM_ALG_SM4
+
+NOTE
+
+sym
+
+TPMI_ALG_SYM_MODE
+
+when selector may be any of the
+symmetric block ciphers
+
+no mode selector
+
+null
+
+TPM_ALG_NULL
+
+no mode selector
+
+Page 106
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.6 TPMU_SYM_DETAILS
+This union allows additional parameters to be added for a symmetric cipher. Currently, no additional
+parameters are required for any of the symmetric algorithms.
+NOTE
+
+The “x” character in the table title will suppress generation of this type as the parser is not, at this time,
+able to generate the proper values (a union of all empty data types). When an algorithm is added that
+requires additional parameterization, the Type column will contain a value and the “x” may be removed.
+
+Table 125 — xDefinition of TPMU_SYM_DETAILS Union
+Parameter
+
+Type
+
+Selector
+
+aes
+
+TPM_ALG_AES
+
+SM4
+
+Description
+
+TPM_ALG_SM4
+
+sym
+
+when selector may be any of the
+symmetric block ciphers
+
+xor
+
+TPM_ALG_XOR
+
+null
+
+TPM_ALG_NULL
+
+11.1.7 TPMT_SYM_DEF
+The TPMT_SYM_DEF structure is used to select an algorithm to be used for parameter encryption in
+those cases when different symmetric algorithms may be selected.
+Table 126 — Definition of TPMT_SYM_DEF Structure
+Parameter
+
+Type
+
+Description
+
+algorithm
+
++TPMI_ALG_SYM
+
+indicates a symmetric algorithm
+
+[algorithm]keyBits
+
+TPMU_SYM_KEY_BITS
+
+a supported key size
+
+[algorithm]mode
+
+TPMU_SYM_MODE
+
+the mode for the key
+
+//[algorithm]details
+
+TPMU_SYM_DETAILS
+
+contains additional algorithm details
+NOTE
+
+This is commented out at this time as the parser
+may not produce the proper code for a union if
+none of the selectors produces any data.
+
+11.1.8 TPMT_SYM_DEF_OBJECT
+This structure is used when different symmetric block cipher (not XOR) algorithms may be selected.
+Table 127 — Definition of TPMT_SYM_DEF_OBJECT Structure
+Parameter
+
+Type
+
+Description
+
+algorithm
+
++TPMI_ALG_SYM_OBJECT
+
+selects a symmetric block cipher
+
+[algorithm]keyBits
+
+TPMU_SYM_KEY_BITS
+
+the key size
+
+[algorithm]mode
+
+TPMU_SYM_MODE
+
+default mode
+
+//[algorithm]details
+
+TPMU_SYM_DETAILS
+
+contains the additional algorithm details, if any
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+This is commented out at this time as the parser
+may not produce the proper code for a union if
+none of the selectors produces any data.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 107
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.1.9 TPM2B_SYM_KEY
+This structure is used to hold a symmetric key in the sensitive area of an asymmetric object.
+The number of bits in the key is in keyBits in the public area. When keyBits is not an even multiple of 8
+bits, the unused bits of buffer will be the most significant bits of buffer[0] and size will be rounded up to
+the number of octets required to hold all bits of the key.
+Table 128 — Definition of TPM2B_SYM_KEY Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size, in octets, of the buffer containing the key; may be
+zero
+
+buffer [size] {:MAX_SYM_KEY_BYTES}
+
+BYTE
+
+the key
+
+11.1.10 TPMS_SYMCIPHER_PARMS
+This structure contains the parameters for a symmetric block cipher object.
+Table 129 — Definition of TPMS_SYMCIPHER_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+sym
+
+TPMT_SYM_DEF_OBJECT
+
+a symmetric block cipher
+
+11.1.11 TPM2B_SENSITIVE_DATA
+This buffer holds the secret data of a data object. It can hold as much as 128 octets of data.
+MAX_SYM_DATA shall be 128.
+NOTE
+
+A named value rather than a numeric is used to make coding clearer. A numeric value does not indicate
+the reason that it has the specific value that is has.
+
+Table 130 — Definition of TPM2B_SENSITIVE_DATA Structure
+Parameter
+
+Type
+
+size
+
+UINT16
+
+buffer[size]{: MAX_SYM_DATA}
+
+BYTE
+
+Page 108
+October 31, 2013
+
+Description
+
+the keyed hash private data structure
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.12 TPMS_SENSITIVE_CREATE
+This structure defines the values to be placed in the sensitive area of a created object. This structure is
+only used within a TPM2B_SENSITIVE_CREATE structure.
+NOTE
+
+When sent to the TPM or unsealed, data is usually encrypted using parameter encryption.
+
+If data.size is not zero, and the object is not a keyedHash, data.size must match the size indicated in the
+keySize of public.parameters. If the object is a keyedHash, data.size may be any value up to the
+maximum allowed in a TPM2B_SENSITIVE_DATA.
+For an asymmetric object, data shall be an Empty Buffer and sensitiveDataOrigin shall be SET.
+Table 131 — Definition of TPMS_SENSITIVE_CREATE Structure <IN>
+Parameter
+
+Type
+
+Description
+
+userAuth
+
+TPM2B_AUTH
+
+the USER auth secret value
+
+data
+
+TPM2B_SENSITIVE_DATA
+
+data to be sealed
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 109
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.1.13 TPM2B_SENSITIVE_CREATE
+This structure contains the sensitive creation data in a sized buffer. This structure is defined so that both
+the userAuth and data values of the TPMS_SENSITIVE_CREATE may be passed as a single parameter
+for parameter encryption purposes.
+Table 132 — Definition of TPM2B_SENSITIVE_CREATE Structure <IN, S>
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of sensitive in octets (may not be zero)
+NOTE
+
+sensitive
+
+TPMS_SENSITIVE_CREATE
+
+The userAuth and data parameters in this buffer
+may both be zero length but the minimum size of
+this parameter will be the sum of the size fields of
+the
+two
+parameters
+of
+the
+TPMS_SENSITIVE_CREATE.
+
+data to be sealed or a symmetric key value.
+
+11.1.14 TPMS_SCHEME_SIGHASH
+This structure is the scheme data for schemes that only require a hash to complete the scheme definition.
+Table 133 — Definition of TPMS_SCHEME_SIGHASH Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+11.1.15 TPMI_ALG_HASH_SCHEME
+This is the list of values that may appear in a keyedHash as the scheme parameter.
+Table 134 — Definition of (TPM_ALG_ID) TPMI_ALG_KEYEDHASH_SCHEME Type
+Values
+
+Comments
+
+TPM_ALG_HMAC
+
+the "signing" scheme
+
+TPM_ALG_XOR
+
+the "obfuscation" scheme
+
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.1.16 HMAC_SIG_SCHEME
+Table 135 — Definition of Types for HMAC_SIG_SCHEME
+Type
+
+Name
+
+TPMS_SCHEME_SIGHASH
+
+TPMS_SCHEME_HMAC
+
+Page 110
+October 31, 2013
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.1.17 TPMS_SCHEME_XOR
+This structure is for the XOR encryption scheme.
+Table 136 — Definition of TPMS_SCHEME_XOR Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+kdf
+
+TPMI_ALG_KDF
+
+the key derivation function
+
+11.1.18 TPMU_SCHEME_HMAC
+Table 137 — Definition of TPMU_SCHEME_KEYEDHASH Union <IN/OUT, S>
+Parameter
+
+Type
+
+Selector
+
+Description
+
+hmac
+
+TPMS_SCHEME_HMAC
+
+TPM_ALG_HMAC
+
+the "signing" scheme
+
+xor
+
+TPMS_SCHEME_XOR
+
+TPM_ALG_XOR
+
+the "obfuscation" scheme
+
+null
+
+TPM_ALG_NULL
+
+11.1.19 TPMT_KEYEDHASH_SCHEME
+This structure is used for a hash signing object.
+Table 138 — Definition of TPMT_KEYEDHASH_SCHEME Structure
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_KEYEDHASH_SCHEME
+
+selects the scheme
+
+[scheme]details
+
+TPMU_SCHEME_KEYEDHASH
+
+the scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 111
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.2 Asymmetric
+11.2.1 Signing Schemes
+11.2.1.1
+
+Introduction
+
+These structures are used to define the method in which the signature is to be created. These schemes
+would appear in an object’s public area and in commands where the signing scheme is variable.
+Every scheme is required to indicate a hash that is used in digesting the message.
+11.2.1.2
+
+RSA_SIG_SCHEMES
+
+These are the RSA schemes that only need a hash algorithm as a scheme parameter.
+For the TPM_ALG_RSAPSS signing scheme, the same hash algorithm is used for digesting TPMgenerated data (an attestation structure) and in the KDF used for the masking operation. The salt size is
+always the largest salt value that will fit into the available space.
+Table 139 — Definition of {RSA} Types for RSA_SIG_SCHEMES
+Type
+
+Name
+
+Description
+
+TPMS_SCHEME_SIGHASH
+TPMS_SCHEME_RSASSA
+TPMS_SCHEME_SIGHASH
+TPMS_SCHEME_RSAPSS
+
+11.2.1.3
+
+ECC_SIG_SCHEMES
+
+These are the ECC schemes that only need a hash algorithm as a controlling parameter.
+Table 140 — Definition of {ECC} Types for ECC_SIG_SCHEMES
+Type
+
+Name
+
+Description
+
+TPMS_SCHEME_SIGHASH
+TPMS_SCHEME_ECDSA
+TPMS_SCHEME_SIGHASH
+TPMS_SCHEME_SM2
+TPMS_SCHEME_SIGHASH
+TPMS_SCHEME_ECSCHNORR
+
+11.2.1.4 TPMS_SCHEME_ECDAA
+Table 141 — Definition of {ECC} TPMS_SCHEME_ECDAA Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+count
+
+UINT16
+
+the counter value that is used between TPM2_Commit() and the sign
+operation
+
+Page 112
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+11.2.1.5
+
+Part 2: Structures
+
+TPMU_SIG_SCHEME
+Table 142 — Definition of TPMU_SIG_SCHEME Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsassa
+
+TPMS_SCHEME_RSASSA
+
+TPM_ALG_RSASSA
+
+the PKCS#1v1.5 scheme
+
+rsapss
+
+TPMS_SCHEME_RSAPSS
+
+TPM_ALG_RSAPSS
+
+the PKCS#1v2.1 PSS scheme
+
+ecdsa
+
+TPMS_SCHEME_ECDSA
+
+TPM_ALG_ECDSA
+
+the ECDSA scheme
+
+sm2
+
+TPMS_SCHEME_SM2
+
+TPM_ALG_SM2
+
+ECDSA from SM2
+
+ecdaa
+
+TPMS_SCHEME_ECDAA
+
+TPM_ALG_ECDAA
+
+the ECDAA scheme
+
+ecSchnorr
+
+TPMS_SCHEME_ECSCHNORR
+
+TPM_ALG_ECSCHNORR
+
+the EC Schnorr
+
+hmac
+
+TPMS_SCHEME_HMAC
+
+TPM_ALG_HMAC
+
+the HMAC scheme
+
+any
+
+TPMS_SCHEME_SIGHASH
+
+null
+
+11.2.1.6
+
+selector that allows access to
+digest for any signing scheme
+TPM_ALG_NULL
+
+no scheme or default
+
+TPMT_SIG_SCHEME
+Table 143 — Definition of TPMT_SIG_SCHEME Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_SIG_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_SIG_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 113
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.2.2 Encryption Schemes
+11.2.2.1
+
+Introduction
+
+These structures are used to indicate the hash algorithm used for the encrypting process. These
+schemes would appear in an object’s public area.
+11.2.2.2
+
+TPMS_SCHEME_OAEP
+Table 144 — Definition of {RSA} TPMS_SCHEME_OAEP Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+
+11.2.2.3
+
+TPMS_SCHEME_ECDH
+
+For ECDH, KDFe is used for the key derivation function that only a hash algorithm is needed to complete
+the definition.
+Table 145 — Definition of {ECC} TPMS_SCHEME_ECDH Structure
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
++TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3 Key Derivation Schemes
+11.2.3.1
+
+Introduction
+
+These structures are used to define the key derivation for symmetric secret sharing using asymmetric
+methods. A secret shareing scheme is required in any asymmetric key with the decrypt attribute SET.
+These schemes would appear in an object’s public area and in commands where the secret sharing
+scheme is variable.
+Each scheme includes a symmetric algorithm and a KDF selection.
+11.2.3.2
+
+TPMS_SCHEME_MGF1
+Table 146 — Definition of TPMS_SCHEME_MGF1 Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3.3
+
+TPMS_SCHEME_KDF1_SP800_56a
+Table 147 — Definition of {ECC} TPMS_SCHEME_KDF1_SP800_56a Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+Page 114
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+11.2.3.4
+
+Part 2: Structures
+
+TPMS_SCHEME_KDF2
+Table 148 — Definition of TPMS_SCHEME_KDF2 Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3.5
+
+TPMS_SCHEME_KDF1_SP800_108
+Table 149 — Definition of TPMS_SCHEME_KDF1_SP800_108 Structure
+
+Parameter
+
+Type
+
+Description
+
+hashAlg
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the KDF
+
+11.2.3.6
+
+TPMU_KDF_SCHEME
+Table 150 — Definition of TPMU_KDF_SCHEME Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+mgf1
+
+TPMS_SCHEME_MGF1
+
+TPM_ALG_MGF1
+
+kdf1_SP800_56a
+
+TPMS_SCHEME_KDF1_SP800_56a
+
+TPM_ALG_KDF1_SP800_56a
+
+kdf2
+
+TPMS_SCHEME_KDF2
+
+TPM_ALG_KDF2
+
+kdf1_sp800_108
+
+TPMS_SCHEME_KDF1_SP800_108
+
+Description
+
+TPM_ALG_KDF1_SP800_108
+
+null
+
+11.2.3.7
+
+TPM_ALG_NULL
+
+TPMT_KDF_SCHEME
+Table 151 — Definition of TPMT_KDF_SCHEME Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_KDF
+
+scheme selector
+
+[scheme]details
+
+TPMU_KDF_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 115
+October 31, 2013
+
+ Part 2: Structures
+11.2.3.8
+
+Trusted Platform Module Library
+
+TPMI_ALG_ASYM_SCHEME
+
+List of all of the scheme types for any asymmetric algorithm. This is used to define the
+TPMT_ASYM_SCHEME.
+Table 152 — Definition of (TPM_ALG_ID) TPMI_ALG_ASYM_SCHEME Type <>
+Values
+
+Comments
+
+TPM_ALG_RSASSA
+
+list of the allowed values
+
+TPM_ALG_RSAPSS
+TPM_ALG_RSAES
+TPM_ALG_OAEP
+TPM_ALG_ECDSA
+TPM_ALG_SM2
+TPM_ALG_ECDAA
+TPM_ALG_ECDH
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.2.3.9
+
+TPMU_ASYM_SCHEME
+
+This union of all asymmetric schemes is used in each of the asymmetric scheme structures. The actual
+scheme structure is defined by the interface type used for the selector.
+EXAMPLE
+
+The TPMT_RSA_SCHEME structure uses the TPMU_ASYM_SCHEME union but the selector type is
+TPMI_ALG_RSA_SCHEME. This means that the only elements of the union that can be selected for th e
+TPMT_RSA_SCHEME are those that are in TPMI_RSA_SCHEME.
+
+Table 153 — Definition of TPMU_ASYM_SCHEME Union
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsassa
+
+TPMS_SCHEME_RSASSA
+
+TPM_ALG_RSASSA
+
+the PKCS#1v1.5 scheme
+
+rsapss
+
+TPMS_SCHEME_RSAPSS
+
+TPM_ALG_RSAPSS
+
+the PKCS#1v2.1 PSS scheme
+
+oaep
+
+TPMS_SCHEME_OAEP
+
+TPM_ALG_OAEP
+
+the PKSC#1v2.1 OAEP scheme
+
+ecdsa
+
+TPMS_SCHEME_ECDSA
+
+TPM_ALG_ECDSA
+
+an ECDSA scheme
+
+sm2
+
+TPMS_SCHEME_SM2
+
+TPM_ALG_SM2
+
+sign or key exchange from SM2
+
+ecdaa
+
+TPMS_SCHEME_ECDAA
+
+TPM_ALG_ECDAA
+
+an ECDAA scheme
+
+ecSchnorr
+
+TPMS_SCHEME_ECSCHNORR
+
+TPM_ALG_ECSCHNORR elliptic curve Schnorr signature
+
+ecdh
+TPMS_SCHEME_ECDH
+TPM_ALG_ECDH
+anySig
+
+TPMS_SCHEME_SIGHASH
+
+null
+
+Page 116
+October 31, 2013
+
+TPM_ALG_NULL
+
+Published
+Copyright © TCG 2006-2013
+
+no scheme or default
+This selects the NULL Signature.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.2.3.10 TPMT_ASYM_SCHEME
+This structure is defined to allow overlay of all of the schemes for any asymmetric object. This structure is
+not sent on the interface.
+Table 154 — Definition of TPMT_ASYM_SCHEME Structure <>
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_ASYM_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_ASYM_SCHEME
+
+scheme parameters
+
+11.2.4 RSA
+11.2.4.1
+
+TPMI_ALG_RSA_SCHEME
+
+The list of values that may appear in the scheme parameter of a TPMS_RSA_PARMS structure.
+Table 155 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_SCHEME Type
+Values
+
+Comments
+
+TPM_ALG_RSASSA
+
+list of the allowed values
+
+TPM_ALG_RSAPSS
+TPM_ALG_RSAES
+TPM_ALG_OAEP
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.2.4.2
+
+TPMT_RSA_SCHEME
+Table 156 — Definition of {RSA} TPMT_RSA_SCHEME Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_RSA_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_ASYM_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 117
+October 31, 2013
+
+ Part 2: Structures
+11.2.4.3
+
+Trusted Platform Module Library
+
+TPMI_ALG_RSA_DECRYPT
+
+The list of values that are allowed in a decryption scheme selection as used in TPM2_RSA_Encrypt() and
+TPM2_RSA_Decrypt().
+Table 157 — Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_DECRYPT Type
+Values
+
+Comments
+
+TPM_ALG_RSAES
+TPM_ALG_OAEP
++TPM_ALG_NULL
+#TPM_RC_VALUE
+
+11.2.4.4
+
+TPMT_RSA_DECRYPT
+Table 158 — Definition of {RSA} TPMT_RSA_DECRYPT Structure
+
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_RSA_DECRYPT
+
+scheme selector
+
+[scheme]details
+
+TPMU_ASYM_SCHEME
+
+scheme parameters
+
+11.2.4.5
+
+TPM2B_PUBLIC_KEY_RSA
+
+This sized buffer holds the largest RSA public key supported by the TPM.
+NOTE
+
+The reference implementation only supports key sizes of 1,024 and 2,048 bits.
+
+Table 159 — Definition of {RSA} TPM2B_PUBLIC_KEY_RSA Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the buffer
+The value of zero is only valid for create.
+
+buffer[size] {: MAX_RSA_KEY_BYTES}
+
+BYTE
+
+Value
+
+11.2.4.6
+
+TPMI_RSA_KEY_BITS
+
+This holds the value that is the maximum size allowed for an RSA key.
+NOTE 1
+
+An implementation is allowed to provide limited support for smaller RSA key sizes. That is, a TPM may be
+able to accept a smaller RSA key size in TPM2_LoadExternal() when only the public area is loaded but
+not accept that smaller key size in any command that loads both the public and private portions of an RSA
+key. This would allow the TPM to validate signatures using the smaller key but would prevent the TPM
+from using the smaller key size for any other purpose.
+
+NOTE 2
+
+The definition for RSA_KEY_SIZES_BITS used in the reference implementation is found in Annex B
+
+Page 118
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 160 — Definition of {RSA} (TPM_KEY_BITS) TPMI_RSA_KEY_BITS Type
+Parameter
+
+Description
+
+$RSA_KEY_SIZES_BITS
+
+the number of bits in the supported key
+
+#TPM_RC_VALUE
+
+error when key size is not supported
+
+11.2.4.7
+
+TPM2B_PRIVATE_KEY_RSA
+
+This sized buffer holds the largest RSA prime number supported by the TPM.
+NOTE
+
+All primes are required to have exactly half the number of significant bits as the public modulus , and the
+square of each prime is required to have the same number of significant bits as the public modulus.
+
+Table 161 — Definition of {RSA} TPM2B_PRIVATE_KEY_RSA Structure
+Parameter
+
+Type
+
+size
+
+UINT16
+
+buffer[size]{:MAX_RSA_KEY_BYTES/2}
+
+BYTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Description
+
+Published
+Copyright © TCG 2006-2013
+
+Page 119
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.2.5 ECC
+11.2.5.1
+
+TPM2B_ECC_PARAMETER
+
+This sized buffer holds the largest ECC parameter (coordinate) supported by the TPM.
+Table 162 — Definition of {ECC} TPM2B_ECC_PARAMETER Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of buffer
+
+buffer[size] {:MAX_ECC_KEY_BYTES}
+
+BYTE
+
+the parameter data
+
+11.2.5.2
+
+TPMS_ECC_POINT
+
+This structure holds two ECC coordinates that, together, make up an ECC point.
+Table 163 — Definition of {ECC} TPMS_ECC_POINT Structure
+Parameter
+
+Type
+
+Description
+
+x
+
+TPM2B_ECC_PARAMETER
+
+X coordinate
+
+y
+
+TPM2B_ECC_PARAMETER
+
+Y coordinate
+
+11.2.5.3
+
+TPM2B_ECC_POINT
+
+This structure is defined to allow a point to be a single sized parameter so that it may be encrypted.
+NOTE
+
+If the point is to be omitted, the X and Y coordinates need to be individual ly set to Empty Buffers. The
+minimum value for size will be four. It is checked indirectly by unmarshaling of the TPMS_ECC_POINT. If
+the type of point were BYTE, then size could have been zero. However, this would complicate the process
+of marshaling the structure.
+
+Table 164 — Definition of {ECC} TPM2B_ECC_POINT Structure
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of the remainder of this structure
+
+point
+
+TPMS_ECC_POINT
+
+coordinates
+error returned if the unmarshaled size of point is
+not exactly equal to size
+
+#TPM_RC_SIZE
+
+Page 120
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+11.2.5.4
+
+Part 2: Structures
+
+TPMI_ALG_ECC_SCHEME
+Table 165 — Definition of (TPM_ALG_ID) {ECC} TPMI_ALG_ECC_SCHEME Type
+
+Values
+
+Comments
+
+TPM_ALG_ECDSA
+
+these are the selections allowed for an ECC key
+
+TPM_ALG_SM2
+TPM_ALG_ECDAA
+TPM_ALG_ECSCHNORR
+TPM_ALG_ECDH
++TPM_ALG_NULL
+#TPM_RC_SCHEME
+
+11.2.5.5
+
+TPMI_ECC_CURVE
+
+The ECC curves implemented by the TPM.
+NOTE
+
+The definition of ECC_CURVES used in the reference implementation is found in Annex B
+
+Table 166 — Definition of {ECC} (TPM_ECC_CURVE) TPMI_ECC_CURVE Type
+Parameter
+
+Description
+
+$ECC_CURVES
+
+the list of implemented curves
+
+#TPM_RC_CURVE
+
+error when curve is not supported
+
+11.2.5.6
+
+TPMT_ECC_SCHEME
+
+Table 167 — Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure
+Parameter
+
+Type
+
+Description
+
+scheme
+
++TPMI_ALG_ECC_SCHEME
+
+scheme selector
+
+[scheme]details
+
+TPMU_SIG_SCHEME
+
+scheme parameters
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 121
+October 31, 2013
+
+ Part 2: Structures
+11.2.5.7
+
+Trusted Platform Module Library
+
+TPMS_ALGORITHM_DETAIL_ECC
+
+This structure is used to report on the curve parameters of an ECC curve. It is returned by
+TPM2_ECC_Parameters().
+Table 168 — Definition of {ECC} TPMS_ALGORITHM_DETAIL_ECC Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+curveID
+
+TPM_ECC_CURVE
+
+identifier for the curve
+
+keySize
+
+UINT16
+
+Size in bits of the key
+
+kdf
+
+TPMT_KDF_SCHEME
+
+the default KDF and hash algorithm used in secret sharing
+operations
+
+sign
+
+TPMT_ECC_SCHEME+
+
+If not TPM_ALG_NULL, this is the mandatory signature
+scheme that is required to be used with this curve.
+
+p
+
+TPM2B_ECC_PARAMETER
+
+Fp (the modulus)
+
+a
+
+TPM2B_ECC_PARAMETER
+
+coefficient of the linear term in the curve equation
+
+b
+
+TPM2B_ECC_PARAMETER
+
+constant term for curve equation
+
+gX
+
+TPM2B_ECC_PARAMETER
+
+x coordinate of base point G
+
+gY
+
+TPM2B_ECC_PARAMETER
+
+y coordinate of base point G
+
+n
+
+TPM2B_ECC_PARAMETER
+
+order of G
+
+h
+
+TPM2B_ECC_PARAMETER
+
+cofactor (a size of zero indicates a cofactor of 1)
+
+11.3 Signatures
+11.3.1 TPMS_SIGNATURE_RSASSA
+Table 169 — Definition of {RSA} TPMS_SIGNATURE_RSASSA Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm used to digest the message
+TPM_ALG_NULL is not allowed.
+
+sig
+
+TPM2B_PUBLIC_KEY_RSA
+
+The signature is the size of a public key.
+
+11.3.2 TPMS_SIGNATURE_RSAPSS
+When the TPM generates a PSS signature, the salt size is the largest size allowed by the key and hash
+combination.
+EXAMPLE
+
+For a 2,048-bit public modulus key and SHA1 hash, the salt size is 256 – 20 – 2 = 234 octets.
+
+NOTE
+
+While this is significantly larger than required from a securit y perspective, it avoids issues of whether a
+particular size of salt value is sufficient.
+
+Page 122
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 170 — Definition of {RSA} TPMS_SIGNATURE_RSAPSS Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the signature process
+TPM_ALG_NULL is not allowed.
+
+sig
+
+TPM2B_PUBLIC_KEY_RSA
+
+The signature is the size of a public key.
+
+11.3.3 TPMS_SIGNATURE_ECDSA
+Table 171 — Definition of {ECC} TPMS_SIGNATURE_ECDSA Structure
+Parameter
+
+Type
+
+Description
+
+hash
+
+TPMI_ALG_HASH
+
+the hash algorithm used in the signature process
+TPM_ALG_NULL is not allowed.
+
+signatureR
+
+TPM2B_ECC_PARAMETER
+
+signatureS
+
+TPM2B_ECC_PARAMETER
+
+11.3.4 TPMU_SIGNATURE
+A TPMU_SIGNATURE_COMPOSITE is a union of the various signatures that is supported by a particular
+TPM implementation. The union allows substitution of any signature algorithm wherever a signature is
+required in a structure. Table 172 is an illustration of a TPMU_SIGNATURE for a TPM that implements
+both RSA and ECC signing.
+NOTE 1
+
+All TPM are required to support a hash algorithm and the HMAC algorithm.
+
+When a symmetric algorithm is used for signing, the signing algorithm is assumed to be an HMAC based
+on the indicated hash algorithm. The HMAC key will either be referenced as part of the usage or will be
+implied by context.
+NOTE 2
+
+The table below is illustrative. It would be modified to reflect the signatures produced by the TPM.
+
+Table 172 — Definition of TPMU_SIGNATURE Union <IN/OUT, S>
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsassa
+
+TPMS_SIGNATURE_RSASSA
+
+TPM_ALG_RSASSA
+
+a PKCS#1v1.5 signature
+
+rsapss
+
+TPMS_SIGNATURE_RSAPSS
+
+TPM_ALG_RSAPSS
+
+a PKCS#1v2.1PSS signature
+
+ecdsa
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_ECDSA
+
+an ECDSA signature
+
+sm2
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_SM2
+
+same format as ECDSA
+
+ecdaa
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_ECDAA
+
+same format as ECDSA
+
+ecschnorr
+
+TPMS_SIGNATURE_ECDSA
+
+TPM_ALG_ECSCHNORR
+
+same format as ECDSA
+
+hmac
+
+TPMT_HA
+
+TPM_ALG_HMAC
+
+HMAC signature (required to
+be supported)
+
+any
+
+TPMS_SCHEME_SIGHASH
+
+null
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+the NULL signature
+
+Page 123
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+11.3.5 TPMT_SIGNATURE
+Table 173 shows the basic algorithm-agile structure when a symmetric or asymmetric signature is
+indicated. The sigAlg parameter indicates the algorithm used for the signature. This structure is output
+from the attestation commands and is an input to TPM2_VerifySignature(), TPM2_PolicySigned(), and
+TPM2_FieldUpgradeStart().
+Table 173 — Definition of TPMT_SIGNATURE Structure
+Parameter
+
+Type
+
+Description
+
+sigAlg
+
++TPMI_ALG_SIG_SCHEME
+
+selector of the algorithm used to construct the signature
+
+[sigAlg]signature
+
+TPMU_SIGNATURE
+
+This shall be the actual signature information.
+
+11.4 Key/Secret Exchange
+11.4.1 Introduction
+The structures in this clause are used when a key or secret is being exchanged. The exchange may be in
+
+
+TPM2_StartAuthSession() where the secret is injected for salting the session,
+
+
+
+TPM2_Duplicate(), TPM2_Import, or TPM2_Rewrap() where the secret is the symmetric encryption
+key for the outer wrapper of a duplication blob, or
+
+
+
+TPM2_ActivateIdentity() or TPM2_CreateIdentity() where the secret is the symmetric encryption key
+for the credential blob.
+
+Particulars are described in Part 1.
+11.4.2 TPMU_ENCRYPTED_SECRET
+This structure is used to hold either an ephemeral public point for ECDH, an OAEP-encrypted block for
+RSA, or a symmetrically encrypted value. This structure is defined for the limited purpose of determining
+the size of a TPM2B_ENCRYPTED_SECRET.
+The symmetrically encrypted value may use either CFB or XOR encryption.
+NOTE
+
+Table 174 is illustrative. It would be modified depending on the algorithms supported in the TPM.
+
+Table 174 — Definition of TPMU_ENCRYPTED_SECRET Union <S>
+Parameter
+
+Type
+
+Selector
+
+ecc[sizeof(TPMS_ECC_POINT)]
+
+BYTE
+
+TPM_ALG_ECC
+
+rsa[MAX_RSA_KEY_BYTES]
+
+BYTE
+
+TPM_ALG_RSA
+
+symmetric[sizeof(TPM2B_DIGEST)]
+
+BYTE
+
+TPM_ALG_SYMCIPHER
+
+keyedHash[sizeof(TPM2B_DIGEST)]
+
+BYTE
+
+TPM_ALG_KEYEDHASH
+
+Page 124
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Description
+
+Any symmetrically encrypted
+secret value will be limited to
+be no larger than a digest.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+11.4.3 TPM2B_ENCRYPTED_SECRET
+Table 175 — Definition of TPM2B_ENCRYPTED_SECRET Structure
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the secret value
+
+secret[size] {:sizeof(TPMU_ENCRYPTED_SECRET)}
+
+BYTE
+
+secret
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 125
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+12 Key/Object Complex
+12.1 Introduction
+An object description requires a TPM2B_PUBLIC structure and may require a TPMT_SENSITIVE
+structure. When the structure is stored off the TPM, the TPMT_SENSITIVE structure is encrypted within a
+TPM2B_PRIVATE structure.
+When the object requires two components for its description, those components are loaded as separate
+parameters in the TPM2_Load() command. When the TPM creates an object that requires both
+components, the TPM will return them as separate parameters from the TPM2_Create() operation.
+The TPM may produce multiple different TPM2B_PRIVATE structures for a single TPM2B_PUBLIC
+structure. Creation of a modified TPM2B_PRIVATE structure requires that the full structure be loaded with
+the TPM2_Load() command, modification of the TPMT_SENSITIVE data, and output of a new
+TPM2B_PRIVATE structure.
+12.2 Public Area Structures
+12.2.1 Description
+This clause defines the TPM2B_PUBLIC structure and the higher-level substructure that may be
+contained in a TPM2B_PUBLIC. The higher-level structures that are currently defined for inclusion in a
+TPM2B_PUBLIC are the
+
+
+structures for asymmetric keys,
+
+
+
+structures for symmetric keys, and
+
+
+
+structures for sealed data.
+
+12.2.2 TPMI_ALG_PUBLIC
+Table 176 — Definition of (TPM_ALG_ID) TPMI_ALG_PUBLIC Type
+Values
+
+Comments
+
+TPM_ALG_KEYEDHASH
+
+required of all TPM
+
+TPM_ALG_SYMCIPHER
+
+required of all TPM
+
+TPM_ALG_RSA
+
+At least one asymmetric algorithm shall be implemented.
+
+TPM_ALG_ECC
+
+At least one asymmetric algorithm shall be implemented.
+
+#TPM_RC_TYPE
+
+response code when a public type is not supported
+
+12.2.3 Type-Specific Parameters
+12.2.3.1
+
+Description
+
+The public area contains two fields (parameters and unique) that vary by object type. The parameters
+field varies according to the type of the object but the contents may be the same across multiple
+instances of a particular type. The unique field format also varies according to the type of the object and
+will also be unique for each instance.
+
+Page 126
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+For a symmetric key (type == TPM_ALG_SYMCIPHER), HMAC key (type == TPM_ALG_KEYEDHASH)
+or data object (also, type == TPM_ALG_KEYEDHASH), the contents of unique shall be computed from
+components of the sensitive area of the object as follows:
+
+unique ≔ HnameAlg(seedValue || sensitive)
+
+(8)
+
+where
+
+HnameAlg()
+
+the hash algorithm used to compute the Name of the object
+
+seedValue
+
+the digest-sized obfuscation value in the sensitive area of a symmetric
+key
+or
+symmetric
+data
+object
+found
+in
+a
+TPMT_SENSITIVE.seedValue.buffer
+
+sensitive
+
+the
+secret
+key/data
+of
+TPMT_SENSITIVE.sensitive.any.buffer
+
+12.2.3.2
+
+the
+
+object
+
+in
+
+the
+
+TPMU_PUBLIC_ID
+Table 177 — Definition of TPMU_PUBLIC_ID Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+keyedHash
+
+TPM2B_DIGEST
+
+TPM_ALG_KEYEDHASH
+
+sym
+
+TPM2B_DIGEST
+
+TPM_ALG_SYMCIPHER
+
+rsa
+
+TPM2B_PUBLIC_KEY_RSA
+
+TPM_ALG_RSA
+
+ecc
+
+TPMS_ECC_POINT
+
+TPM_ALG_ECC
+
+12.2.3.3
+
+Description
+
+TPMS_KEYEDHASH_PARMS
+
+This structure describes the parameters that would appear in the public area of a KEYEDHASH object.
+Note
+
+Although the names are the same, the types of the structures are not the same as for asymmetric
+parameter lists.
+
+Table 178 — Definition of TPMS_KEYEDHASH_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+scheme
+
+TPMT_KEYEDHASH_SCHEME+
+
+Indicates the signing method used for a keyedHash signing
+object. This field also determines the size of the data field for a
+data object created with TPM2_Create(). This field shall not be set
+to TPM_ALG_NULL in a template if either sign or encrypt is SET.
+
+12.2.3.4
+
+TPMS_ASYM_PARMS
+
+This structure contains the common public area parameters for an asymmetric key. The first two
+parameters of the parameter definition structures of an asymmetric key shall have the same two first
+components.
+NOTE
+
+The sign parameter may have a different type in order to allow different schemes to be selected for each
+asymmetric type but the first parameter of each scheme definition shall be a TPM_ALG_ID for a valid
+signing scheme.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 127
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+Table 179 — Definition of TPMS_ASYM_PARMS Structure <>
+
+Parameter
+
+Type
+
+Description
+
+symmetric
+
+TPMT_SYM_DEF_OBJECT+
+
+the companion symmetric algorithm for a restricted
+decryption key and shall be set to a supported symmetric
+algorithm
+This field is optional for keys that are not decryption keys
+and shall be set to TPM_ALG_NULL if not used.
+
+scheme
+
+TPMT_ASYM_SCHEME+
+
+for a key with the sign attribute SET, a valid signing
+scheme for the key type
+for a key with the decrypt attribute SET, a valid key
+exchange protocol
+for a key with sign and decrypt attributes, shall be TPM_ALG_NULL
+
+12.2.3.5
+
+TPMS_RSA_PARMS
+
+A TPM compatible with this specification and supporting RSA shall support numPrimes of two and an
+exponent of zero. Support for other values is optional. Use of other exponents in duplicated keys is not
+recommended because the resulting keys would not be interoperable with other TPMs.
+NOTE 1
+
+Implementations are not required to check that exponent is the default exponent. They may fail to load the
+key if exponent is not zero. The reference implementation allows the values listed in the table.
+
+Table 180 — Definition of {RSA} TPMS_RSA_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+symmetric
+
+TPMT_SYM_DEF_OBJECT+
+
+for a restricted decryption key, shall be set to a
+supported symmetric algorithm, key size, and mode.
+if the key is not a restricted decryption key, this field
+shall be set to TPM_ALG_NULL.
+
+scheme
+
+TPMT_RSA_SCHEME+
+
+
+keyBits
+
+TPMI_RSA_KEY_BITS
+
+number of bits in the public modulus
+
+exponent
+UINT32
+
+the public exponent
+A prime number greater than 2.
+When zero, indicates that the exponent is the default
+16
+of 2 + 1
+
+#TPM_RC_KEY_SIZE
+
+#TPM_RC_VALUE
+
+Page 128
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+12.2.3.6
+
+Part 2: Structures
+
+TPMS_ECC_PARMS
+
+This structure contains the parameters for prime modulus ECC.
+Table 181 — Definition of {ECC} TPMS_ECC_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+symmetric
+
+TPMT_SYM_DEF_OBJECT+
+
+for a restricted decryption key, shall be set to a supported
+symmetric algorithm, key size. and mode.
+if the key is not a restricted decryption key, this field shall be
+set to TPM_ALG_NULL.
+
+scheme
+
+TPMT_ECC_SCHEME+
+
+If the sign attribute of the key is SET, then this shall be a valid
+signing scheme.
+NOTE
+
+If the sign parameter in curveID indicates a mandatory
+scheme, then this field shall have the same value.
+
+curveID
+TPMI_ECC_CURVE
+
+ECC curve ID
+
+kdf
+
+TPMT_KDF_SCHEME+
+
+
+12.2.3.7
+
+There are currently no commands where this parameter
+has effect and, in the reference code, this field needs to
+be set to TPM_ALG_NULL.
+
+TPMU_PUBLIC_PARMS
+
+Table 182 defines the possible parameter definition structures that may be contained in the public portion
+of a key.
+Table 182 — Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S>
+Parameter
+
+Type
+
+(1)
+
+Selector
+
+Description
+
+keyedHashDetail
+
+TPMS_KEYEDHASH_PARMS
+
+TPM_ALG_KEYEDHASH
+
+sign | encrypt | neither
+
+symDetail
+
+TPMS_SYMCIPHER_PARMS
+
+TPM_ALG_SYMCIPHER
+
+a symmetric block cipher
+
+rsaDetail
+
+TPMS_RSA_PARMS
+
+TPM_ALG_RSA
+
+decrypt + sign
+
+(2)
+
+eccDetail
+
+TPMS_ECC_PARMS
+
+TPM_ALG_ECC
+
+decrypt + sign
+
+(2)
+
+asymDetail
+
+TPMS_ASYM_PARMS
+
+common scheme structure
+for RSA and ECC keys
+
+NOTES
+1)
+
+Description column indicates which of TPMA_OBJECT.decrypt or TPMA_OBJECT.sign may be set.
+
+2)
+
+“+” indicates that both may be set but one shall be set. “|” indicates the optional settings.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 129
+October 31, 2013
+
+ Part 2: Structures
+12.2.3.8
+
+Trusted Platform Module Library
+
+TPMT_PUBLIC_PARMS
+
+This structure is used in TPM2_TestParms() to validate that a set of algorithm parameters is supported by
+the TPM.
+Table 183 — Definition of TPMT_PUBLIC_PARMS Structure
+Parameter
+
+Type
+
+Description
+
+type
+
+TPMI_ALG_PUBLIC
+
+the algorithm to be tested
+
+[type]parameters
+
+TPMU_PUBLIC_PARMS
+ the algorithm details
+
+12.2.4 TPMT_PUBLIC
+Table 184 defines the public area structure. The Name of the object is nameAlg concatenated with the
+digest of this structure using nameAlg.
+Table 184 — Definition of TPMT_PUBLIC Structure
+Parameter
+
+Type
+
+Description
+
+type
+
+TPMI_ALG_PUBLIC
+
+“algorithm” associated with this object
+
+nameAlg
+
++TPMI_ALG_HASH
+
+algorithm used for computing the Name of the object
+NOTE
+
+The "+" indicates that the instance of a TPMT_PUBLIC may have
+a "+" to indicate that the nameAlg may be TPM_ALG_NULL.
+
+objectAttributes
+
+TPMA_OBJECT
+
+attributes that, along with type, determine the manipulations of this
+object
+
+authPolicy
+
+TPM2B_DIGEST
+
+optional policy for using this key
+The policy is computed using the nameAlg of the object.
+NOTE
+
+Shall be the Empty Buffer if no authorization policy is present.
+
+[type]parameters
+
+TPMU_PUBLIC_PARMS
+
+the algorithm or structure details
+
+[type]unique
+
+TPMU_PUBLIC_ID
+
+Page 130
+October 31, 2013
+
+the unique identifier of the structure
+For an asymmetric key, this would be the public key.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+12.2.5 TPM2B_PUBLIC
+This sized buffer is used to embed a TPMT_PUBLIC in a command.
+Table 185 — Definition of TPM2B_PUBLIC Structure
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of publicArea
+NOTE
+
+publicArea
+
++TPMT_PUBLIC
+
+The “=” will force the TPM to try to unmarshal a
+TPMT_PUBLIC and check that the unmarshaled size
+matches the value of size. If all the required fields of
+a TPMT_PUBLIC are not present, the TPM will return
+an error (generally TPM_RC_SIZE) when attempting
+to unmarshal the TPMT_PUBLIC.
+
+the public area
+NOTE
+
+The “+” indicates that the caller may specify that use
+of TPM_ALG_NULL is allowed for nameAlg.
+
+12.3 Private Area Structures
+12.3.1 Introduction
+The structures in 12.3 define the contents and construction of the private portion of a TPM object. A
+TPM2B_PRIVATE along with a TPM2B_PUBLIC are needed to describe a TPM object.
+A TPM2B_PRIVATE area may be encrypted by different symmetric algorithms or, in some cases, not
+encrypted at all.
+12.3.2 Sensitive Data Structures
+12.3.2.1
+
+Introduction
+
+The structures in 12.3.2 define the presumptive internal representations of the sensitive areas of the
+various entities. A TPM may store the sensitive information in any desired format but when constructing a
+TPM_PRIVATE, the formats in this clause shall be used.
+12.3.2.2
+
+TPM2B_PRIVATE_VENDOR_SPECIFIC
+
+This structure is defined for coding purposes. For IO to the TPM, the sensitive portion of the key will be in
+a canonical form. For an RSA key, this will be one of the prime factors of the public modulus. After
+loading, it is typical that other values will be computed so that computations using the private key will not
+need to start with just one prime factor. This structure allows the vendor-specific structure to use the
+space of the
+The value for RSA_VENDOR_SPECIFIC is determined by the vendor.
+Table 186 — Definition of {RSA} TPM2B_PRIVATE_VENDOR_SPECIFIC Structure<>
+Parameter
+
+Type
+
+size
+
+UINT16
+
+buffer[size]{:PRIVATE_VENDOR_SPECIFIC_BYTES}
+
+BYTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Description
+
+Page 131
+October 31, 2013
+
+ Part 2: Structures
+12.3.2.3
+
+Trusted Platform Module Library
+
+TPMU_SENSITIVE_COMPOSITE
+Table 187 — Definition of TPMU_SENSITIVE_COMPOSITE Union <IN/OUT, S>
+
+Parameter
+
+Type
+
+Selector
+
+Description
+
+rsa
+
+TPM2B_PRIVATE_KEY_RSA
+
+TPM_ALG_RSA
+
+a prime factor of the public
+key
+
+ecc
+
+TPM2B_ECC_PARAMETER
+
+TPM_ALG_ECC
+
+the integer private key
+
+bits
+
+TPM2B_SENSITIVE_DATA
+
+TPM_ALG_KEYEDHASH
+
+the private data
+
+sym
+
+TPM2B_SYM_KEY
+
+TPM_ALG_SYMCIPHER
+
+the symmetric key
+
+any
+
+TPM2B_PRIVATE_VENDOR_SPECIFIC
+
+12.3.2.4
+
+vendor-specific size for key
+storage
+
+TPMT_SENSITIVE
+Table 188 — Definition of TPMT_SENSITIVE Structure
+
+Parameter
+
+Type
+
+Description
+
+sensitiveType
+
+TPMI_ALG_PUBLIC
+
+identifier for the sensitive area
+This shall be the same as the type parameter of the
+associated public area.
+
+authValue
+
+TPM2B_AUTH
+
+user authorization data
+The authValue may be a zero-length string.
+This value shall not be larger than the size of the
+digest produced by the nameAlg of the object.
+
+seedValue
+
+TPM2B_DIGEST
+
+for asymmetric key object, the optional protection
+seed; for other objects, the obfuscation value
+This value shall not be larger than the size of the
+digest produced by nameAlg of the object.
+
+[sensitiveType]sensitive
+
+TPMU_SENSITIVE_COMPOSITE
+
+the type-specific private data
+
+12.3.3 TPM2B_SENSITIVE
+The TPM2B_SENSITIVE structure is used as a parameter in TPM2_LoadExternal(). It is an unencrypted
+sensitive area but it may be encrypted using parameter encryption.
+NOTE
+
+When this structure is unmarshaled, the size of the sensitiveType determines what type of value is
+unmarshaled. Each value of sensitiveType is associated with a TPM2B. It is the maximum size for each of
+the TPM2B values will determine if the unmarshal operation is successful . Since there is no selector for
+the any or vendor options for the union, the maximum input and output sizes for a TMP2B_SENSITIVE
+are not affected by the sizes of those parameters.
+
+Table 189 — Definition of TPM2B_SENSITIVE Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the private structure
+
+sensitiveArea
+
+TPMT_SENSITIVE
+
+an unencrypted sensitive area
+
+Page 132
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+12.3.4 Encryption
+A TPMS_SENSITIVE is the input to the encryption process. All TPMS_ENCRYPT structures are CFBencrypted using a key and Initialization Vector (IV) that are derived from a seed value.
+The method of generating the key and IV is described in “Protected Storage” subclause “Symmetric
+Encryption.” in Part 1.
+12.3.5 Integrity
+The integrity computation is used to ensure that a protected object is modified when stored in memory
+outside of the TPM.
+The method of protecting the integrity of the sensitive area is described in “Protected Storage” subclause
+“Integrity” in Part 1.
+12.3.6 _PRIVATE
+This structure is defined to size the contents of a TPM2B_PRIVATE. This structure is not directly
+marshaled or unmarshaled.
+For TPM2_Duplicate() and TPM2_Import(), the TPM2B_PRIVATE may contain multiply encrypted data
+and two integrity values. In some cases, the sensitive data is not encrypted and the integrity value is not
+present.
+For TPM2_Load() and TPM2_Create(), integrityInner is always present.
+If integrityInner is present, it and sensitive are encrypted as a single block.
+When an integrity value is not needed, it is not present and it is not represented by an Empty Buffer.
+Table 190 — Definition of _PRIVATE Structure <>
+Parameter
+
+Type
+
+Description
+
+integrityOuter
+
+TPM2B_DIGEST
+
+integrityInner
+
+TPM2B_DIGEST
+
+could also be a TPM2B_IV
+
+sensitive
+
+TPMT_SENSITIVE
+
+the sensitive area
+
+12.3.7 TPM2B_PRIVATE
+The TPM2B_PRIVATE structure is used as a parameter in multiple commands that create, load, and
+modify the sensitive area of an object.
+Table 191 — Definition of TPM2B_PRIVATE Structure <IN/OUT, S>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the private structure
+
+buffer[size] {:sizeof(_PRIVATE)}
+
+BYTE
+
+an encrypted private area
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 133
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+12.4 Identity Object
+12.4.1 Description
+An identity object is used to convey credential protection value (CV) to a TPM that can load the object
+associated with the object. The CV is encrypted to a storage key on the target TPM, and if the credential
+integrity checks and the proper object is loaded in the TPM, then the TPM will return the CV.
+12.4.2 _ID_OBJECT
+This structure is used for sizing the TPM2_ID_OBJECT.
+Table 192 — Definition of _ID_OBJECT Structure <>
+Parameter
+
+Type
+
+Description
+
+integrityHMAC
+
+TPM2B_DIGEST
+
+encIdentity
+
+TPM2B_DIGEST
+
+credential protector information returned if name matches the
+referenced object
+All of the encIdentity is encrypted, including the size field.
+NOTE
+
+The TPM is not required to check that the size is not larger
+than the digest of the nameAlg. However, if the size is
+larger, the ID object may not be usable on a TPM that has
+no digest larger than produced by nameAlg.
+
+12.4.3 TPM2B_ID_OBJECT
+This structure is an output from TPM2_MakeCredential() and is an input to TPM2_ActivateCredential().
+Table 193 — Definition of TPM2B_ID_OBJECT Structure <IN/OUT>
+Parameter
+
+Type
+
+Description
+
+size
+
+UINT16
+
+size of the credential structure
+
+credential[size]{:sizeof(_ID_OBJECT)}
+
+BYTE
+
+an encrypted credential area
+
+Page 134
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+13 NV Storage Structures
+13.1 TPM_NV_INDEX
+A TPM_NV_INDEX is used to reference a defined location in NV memory. The format of the Index is
+changed from TPM 1.2 in order to include the Index in the reserved handle space. Handles in this range
+use the digest of the public area of the Index as the Name of the entity in authorization computations
+The 32-bit TPM 1.2 NV Index format is shown in Figure 4. In order to allow the Index to fit into the 24 bits
+available in the reserved handle space, the Index value format is changed as shown in Figure 5.
+3 3 2 2 2 2 2 2 2
+1 0 9 8 7 6 5 4 3
+
+1 1
+6 5
+
+T P U D reserved
+
+0
+0
+
+Purview
+
+Index
+
+Figure 4 — TPM 1.2 TPM_NV_INDEX
+3
+1
+
+2 2
+4 3
+
+0
+0
+
+TPM_HT_NV_INDEX
+
+Index
+
+Figure 5 — TPM 2.0 TPM_NV_INDEX
+NOTE
+
+This TPM_NV_INDEX format does not retain the Purview field and the D bit is not a part of an Index
+handle as in TPM 1.2. The TPMA_NV_PLATFORMCREATE attribute is a property of an Index that
+provides functionality similar to the D bit.
+
+A valid Index handle will have an MSO of TPM_HT_NV_INDEX.
+NOTE
+
+This structure is not used. It is defined here to indicate how the fields of the handle are assigned. The
+exemplary unmarshaling code unmarshals a TPM_HANDLE and validates that it is in the range for a
+TPM_NV_INDEX.
+
+Table 194 — Definition of (UINT32) TPM_NV_INDEX Bits <>
+Bit
+
+Name
+
+Definition
+
+23:0
+
+index
+
+The index of the NV location
+
+31:24
+
+RH_NV
+
+constant value of TPM_HT_NV_INDEX indicating the NV Index range
+
+#TPM_RC_VALUE
+
+response code returned if unmarshaling of this type fails because the handle
+value is incorrect
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 135
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+Table 195 — Options for space Field of TPM_NV_INDEX
+
+Some prior versions of this specification contained a table here that assigned subsets of the index field to
+different entities. Since this assignment was a convention and not an architectural element of the TPM,
+the table was removed and the information is now contained in a registry document that is maintained by
+the TCG.
+13.2 TPMA_NV (NV Index Attributes)
+This structure allows the TPM to keep track of the data and permissions to manipulate an NV Index.
+The platform controls (TPMA_NV_PPWRITE and TPMA_NV_PPREAD) and owner controls
+(TPMA_NV_OWNERWRITE and TPMA_NV_OWNERREAD) give the platform and owner access to NV
+Indexes using platformAuth or ownerAuth rather than the authValue or authPolicy of the Index.
+If access to an NV Index is to be restricted based on PCR, then an appropriate authPolicy shall be
+provided.
+NOTE
+
+platformAuth or ownerAuth can be provided in any type of authorization session or as a password.
+
+If TPMA_NV_AUTHREAD is SET, then the Index may be read if the Index authValue is provided. If
+TPMA_NV_POLICYREAD is SET, then the Index may be read if the Index authPolicy is satisfied.
+At least one of TPMA_NV_PPREAD,
+TPMA_NV_POLICYREAD shall be SET.
+
+TPMA_NV_OWNERREAD,
+
+TPMA_NV_AUTHREAD,
+
+or
+
+If TPMA_NV_AUTHWRITE is SET, then the Index may be written if the Index authValue is provided. If
+TPMA_NV_POLICYWRITE is SET, then the Index may be written if the Index authPolicy is satisfied.
+At least one of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE TPMA_NV_AUTHWRITE, or
+TPMA_NV_POLICYWRITE shall be SET.
+If TPMA_NV_WRITELOCKED is SET, then the Index may not be written. If TPMA_NV_WRITEDEFINE is
+SET, TPMA_NV_WRITELOCKED may not be CLEAR except by deleting and redefining the Index. If
+TPMA_NV_WRITEDEFINE is CLEAR, then TPMA_NV_WRITELOCK will be CLEAR on the next
+TPM2_Startup(TPM_SU_CLEAR).
+If TPMA_NV_READLOCKED is SET, then the Index may not be read. TPMA_NV_READLOCK will be
+CLEAR on the next TPM2_Startup(TPM_SU_CLEAR).
+NOTE
+
+The TPM is expected to maintain indicators to indicate that the Index is temporarily locked. The state of
+these indicators is reported in the TPMA_NV_READLOCKED and TPMA_NV_WRITELOCKED attributes.
+
+If TPMA_NV_EXTEND is SET, then writes to the Index will cause an update of the Index using the extend
+operation with the nameAlg used to create the digest.
+Only one of TPMA_NV_EXTEND, TPMA_NV_COUNTER, or TPMA_NV_BITS may be set.
+When
+the
+Index
+is
+created
+(TPM2_NV_DefineSpace()),
+TPMA_NV_WRITELOCKED,
+TPMA_NV_READLOCKED, TPMA_NV_WRITTEN shall all be CLEAR in the parameter that defines the
+attributes of the created Index.
+
+Page 136
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Table 196 — Definition of (UINT32) TPMA_NV Bits
+Bit
+
+Name
+
+Description
+
+0
+
+TPMA_NV_PPWRITE
+
+SET (1): The Index data can be written if platformAuth is provided.
+CLEAR (0): Writing of the Index data cannot be authorized with
+platformAuth.
+
+1
+
+TPMA_NV_OWNERWRITE
+
+SET (1): The Index data can be written if ownerAuth is provided.
+CLEAR (0): Writing of the Index data cannot be authorized with
+ownerAuth.
+
+2
+
+TPMA_NV_AUTHWRITE
+
+SET (1): Authorizations to change the Index contents that require
+USER role may be provided with an HMAC session or password.
+CLEAR (0): Authorizations to change the Index contents that require
+USER role may not be provided with an HMAC session or password.
+
+3
+
+TPMA_NV_POLICYWRITE
+
+SET (1): Authorizations to change the Index contents that require
+USER role may be provided with a policy session.
+CLEAR (0): Authorizations to change the Index contents that require
+USER role may not be provided with a policy session.
+NOTE
+
+TPM2_NV_ChangeAuth() always requires that authorization be
+provided in a policy session.
+
+4
+
+TPMA_NV_COUNTER
+
+SET (1): Index contains an 8-octet value that is to be used as a
+counter and can only be modified with TPM2_NV_Increment().
+CLEAR (0): The Index is not a counter.
+
+5
+
+TPMA_NV_BITS
+
+SET (1): Index contains an 8-octet value to be used as a bit field and
+can only be modified with TPM2_NV_SetBits().
+CLEAR (0): The Index is not a bit field.
+
+6
+
+TPMA_NV_EXTEND
+
+SET (1): Index contains a digest-sized value used like a PCR. The
+Index may only be modified using TPM2_NV_Extend. The extend will
+use the nameAlg of the Index.
+CLEAR (0): Index is not a PCR.
+
+9:7
+
+Reserved
+
+shall be zero
+reserved for use in defining additional write controls
+
+10
+
+TPMA_NV_POLICY_DELETE
+
+SET (1): Index may not be deleted unless the authPolicy is satisfied.
+CLEAR (0): Index may be deleted with proper platform or owner
+authorization.
+
+11
+
+TPMA_NV_WRITELOCKED
+
+SET (1): Index cannot be written.
+CLEAR (0): Index can be written.
+
+12
+
+TPMA_NV_WRITEALL
+
+SET (1): A partial write of the Index data is not allowed. The write
+size shall match the defined space size.
+CLEAR (0): Partial writes are allowed. This setting is required if
+TPMA_NV_BITS is SET.
+
+13
+
+TPMA_NV_WRITEDEFINE
+
+SET (1): TPM2_NV_WriteLock() may be used to prevent further
+writes to this location.
+CLEAR (0): TPM2_NV_WriteLock() does not block subsequent
+writes.
+
+14
+
+TPMA_NV_WRITE_STCLEAR
+
+SET (1): TPM2_NV_WriteLock() may be used to prevent further
+writes to this location until the next TPM Reset or TPM Restart.
+CLEAR (0): A write to this Index with a data size of zero does not
+change the write access.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 137
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Bit
+
+Name
+
+Description
+
+15
+
+TPMA_NV_GLOBALLOCK
+
+SET (1): If TPM2_NV_GlobalWriteLock() is successful, then further
+writes to this location are not permitted until the next TPM Reset or
+TPM Restart.
+CLEAR (0): TPM2_NV_GlobalWriteLock() has no effect on the
+writing of the data at this Index.
+
+16
+
+TPMA_NV_PPREAD
+
+SET (1): The Index data can be read if platformAuth is provided.
+CLEAR (0): Reading of the Index data cannot be authorized with
+platformAuth.
+
+17
+
+TPMA_NV_OWNERREAD
+
+SET (1): The Index data can be read if ownerAuth is provided.
+CLEAR (0): Reading of the Index data cannot be authorized with
+ownerAuth.
+
+18
+
+TPMA_NV_AUTHREAD
+
+SET (1): The Index data may be read if the authValue is provided.
+CLEAR (0): Reading of the Index data cannot be authorized with the
+Index authValue.
+
+19
+
+TPMA_NV_POLICYREAD
+
+SET (1): The Index data may be read if the authPolicy is satisfied.
+CLEAR (0): Reading of the Index data cannot be authorized with the
+Index authPolicy.
+
+Reserved
+
+shall be zero
+reserved for use in defining additional read controls
+
+25
+
+TPMA_NV_NO_DA
+
+SET (1): Authorization failures of the Index do not affect the DA logic
+and authorization of the Index is not blocked when the TPM is in
+Lockout mode.
+CLEAR (0): Authorization failures of the Index will increment the
+authorization failure counter and authorizations of this Index are not
+allowed when the TPM is in Lockout mode.
+
+26
+
+TPMA_NV_ORDERLY
+
+SET (1): NV Index state is only required to be saved when the TPM
+performs an orderly shutdown (TPM2_Shutdown()). Only an Index
+with TPMA_NV_COUNTER SET may have this setting.
+CLEAR (0): NV Index state is required to be persistent after the
+command to update the Index completes successfully (that is, the NV
+update is synchronous with the update command).
+
+27
+
+TPMA_NV_CLEAR_STCLEAR
+
+SET (1): TPMA_NV_WRITTEN for the Index is CLEAR by TPM
+Reset or TPM Restart.
+CLEAR (0): TPMA_NV_WRITTEN is not changed by TPM Restart.
+
+24:20
+
+NOTE
+
+This attribute may only be SET if TPMA_NV_COUNTER is not
+SET.
+
+NOTE
+
+If the TPMA_NV_ORDERLY is SET, TPMA_NV_WRITTEN will
+be CLEAR by TPM Reset.
+
+28
+
+TPMA_NV_READLOCKED
+
+SET (1): Reads of the Index are blocked until the next TPM Reset or
+TPM Restart.
+CLEAR (0): Reads of the Index are allowed if proper authorization is
+provided.
+
+29
+
+TPMA_NV_WRITTEN
+
+SET (1): Index has been written.
+CLEAR (0): Index has not been written.
+
+30
+
+TPMA_NV_PLATFORMCREATE
+
+SET (1): This Index may be undefined with platformAuth but not with
+ownerAuth.
+CLEAR (0): This Index may be undefined using ownerAuth but not
+with platformAuth.
+The TPM will validate that this attribute is SET when the Index is
+defined using platformAuth and will validate that this attribute is
+CLEAR when the Index is defined using ownerAuth.
+
+Page 138
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Bit
+
+Name
+
+Description
+
+31
+
+TPMA_NV_READ_STCLEAR
+
+SET (1): TPM2_NV_ReadLock() may be used to SET
+TPMA_NV_READLOCKED for this Index.
+CLEAR (0): TPM2_NV_ReadLock() has no effect on this Index.
+
+13.3 TPMS_NV_PUBLIC
+This structure describes an NV Index.
+Table 197 — Definition of TPMS_NV_PUBLIC Structure
+Name
+
+Type
+
+Description
+
+nvIndex
+
+TPMI_RH_NV_INDEX
+
+the handle of the data area
+
+nameAlg
+
+TPMI_ALG_HASH
+
+hash algorithm used to compute the name of the
+Index and used for the authPolicy
+
+attributes
+
+TPMA_NV
+
+the Index attributes
+
+authPolicy
+
+TPM2B_DIGEST
+
+the access policy for the Index
+
+dataSize{:MAX_NV_INDEX_SIZE}
+
+UINT16
+
+the size of the data area
+The
+maximum
+size is implementationdependent. The minimum maximum size is
+platform-specific.
+
+#TPM_RC_SIZE
+
+response code returned when the requested size
+is too large for the implementation
+
+13.4 TPM2B_NV_PUBLIC
+This structure is used when a TPMS_NV_PUBLIC is sent on the TPM interface.
+Table 198 — Definition of TPM2B_NV_PUBLIC Structure
+Name
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of nvPublic
+
+nvPublic
+
+TPMS_NV_PUBLIC
+
+the public area
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 139
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+14 Context Data
+14.1 Introduction
+This clause defines the contents of the
+TPM2_ContextLoad() command parameters.
+
+TPM2_ContextSave()
+
+response
+
+parameters
+
+and
+
+If the parameters provided by the caller in TPM2_ContextLoad() do not match the values returned by the
+TPM when the context was saved, the integrity check of the TPM2B_CONTEXT will fail and the object or
+session will not be loaded.
+14.2 TPM2B_CONTEXT_SENSITIVE
+This structure holds the object or session context data. When saved, the full structure is encrypted.
+Table 199 — Definition of TPM2B_CONTEXT_SENSITIVE Structure <IN/OUT>
+Parameter
+
+Type
+
+size
+
+Description
+
+UINT16
+
+buffer[size]{:MAX_CONTEXT_SIZE}
+BYTE
+
+the sensitive data
+
+14.3 TPMS_CONTEXT_DATA
+This structure holds the integrity value and the encrypted data for a context.
+Table 200 — Definition of TPMS_CONTEXT_DATA Structure <IN/OUT, S>
+Parameter
+
+Type
+
+Description
+
+integrity
+
+TPM2B_DIGEST
+
+the integrity value
+
+encrypted
+
+TPM2B_CONTEXT_SENSITIVE
+
+the sensitive area
+
+14.4 TPM2B_CONTEXT_DATA
+This structure is used in a TPMS_CONTEXT.
+Table 201 — Definition of TPM2B_CONTEXT_DATA Structure <IN/OUT>
+Parameter
+
+Type
+
+size
+
+Description
+
+UINT16
+
+buffer[size] {:sizeof(TPMS_CONTEXT_DATA)}
+BYTE
+
+Page 140
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+14.5 TPMS_CONTEXT
+This structure is used in TPM2_ContextLoad() and TPM2_ContextSave(). If the values of the
+TPMS_CONTEXT structure in TPM2_ContextLoad() are not the same as the values when the context
+was saved (TPM2_ContextSave()), then the TPM shall not load the context.
+Saved object contexts shall not be loaded as long as the associated hierarchy is disabled.
+Saved object contexts are invalidated when the Primary Seed of their hierarchy changes. Objects in the
+Endorsement hierarchy are invalidated when either the EPS or SPS is changed.
+When an object has the stClear attribute, it shall not be possible to reload the context or any descendant
+object after a TPM Reset or TPM Restart.
+NOTE 1
+
+The reference implementation prevents reloads after TPM Restart by including the curre nt value of a
+clearCount in the saved object context. When an object is loaded, this value is compared with the current
+value of the clearCount if the object has the stClear attribute. If the values are not the same, then the
+object cannot be loaded.
+
+A sequence value is contained within the integrity-protected part of the saved context. The sequence
+value is repeated in the sequence parameter of the TPMS_CONTEXT of the context. The sequence
+parameter, along with other values, is used in the generation the protection values of the context.
+If the integrity value of the context is valid, but the sequence value of the decrypted context does not
+match the value in the sequence parameter, then TPM shall enter the failure mode because this is
+indicative of a specific type of attack on the context values.
+NOTE 2
+
+If the integrity value is correct, but the decryption fails and produces the wrong value for sequence, this
+implies that either the TPM is faulty or an external entity is able to forge an integrity val ue for the context
+but they have insufficient information to know what the encryption key of the context. Since the TPM
+generated the valid context, then there is no reason for the sequence value in the context to be decrypted
+incorrectly other than the TPM is faulty or the TPM is under attack. In either case, it is appropriate for the
+TPM to enter failure more.
+
+Table 202 — Definition of TPMS_CONTEXT Structure
+Name
+
+Type
+
+Description
+
+sequence
+
+UINT64
+
+the sequence number of the context
+NOTE
+
+Transient object contexts and
+contexts used different counters.
+
+session
+
+savedHandle
+
+TPMI_DH_CONTEXT
+
+the handle of the session, object or sequence
+
+hierarchy
+
+TPMI_RH_HIERARCHY+
+
+the hierarchy of the context
+
+contextBlob
+
+TPM2B_CONTEXT_DATA
+
+the context data and integrity HMAC
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 141
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+14.6 Parameters of TPMS_CONTEXT
+14.6.1 sequence
+The sequence parameter is used to differentiate the contexts and to allow the TPM to create a different
+encryption key for each context. Objects and sessions use different sequence counters. The sequence
+counter for objects (transient and sequence) is incremented when an object context is saved, and the
+sequence counter for sessions increments when a session is created or when it is loaded
+(TPM2_ContextLoad()). The session sequence number is the contextID counter.
+For a session, the sequence number also allows the TRM to find the “older” contexts so that they may be
+refreshed if the contextID are too widely separated.
+If an input value for sequence is larger than the value used in any saved context, the TPM shall return an
+error (TPM_RC_VALUE) and do no additional processing of the context.
+If the context is a session context and the input value for sequence is less than the current value of
+contextID minus the maximum range for sessions, the TPM shall return an error (TPM_RC_VALUE) and
+do no additional processing of the context.
+14.6.2 savedHandle
+For a session, this is the handle that was assigned to the session when it was saved. For a transient
+object, the handle will have one of the values shown in Table 203.
+If the handle type for savedHandle is TPM_HT_TRANSIENT, then the low order bits are used to
+differentiate static objects from sequence objects.
+If an input value for handle is outside of the range of values used by the TPM, the TPM shall return an
+error (TPM_RC_VALUE) and do no additional processing of the context.
+Table 203 — Context Handle Values
+Value
+
+Description
+
+0x02xxxxxx
+
+an HMAC session context
+
+0x03xxxxxx
+
+a policy session context
+
+0x80000000
+
+an ordinary transient object
+
+0x80000001
+
+a sequence object
+
+0x80000002
+
+a transient object with the stClear attribute SET
+
+Page 142
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+14.6.3 hierarchy
+This is the hierarchy (TPMI_RH_HIERARCHY) for the saved context and determines the proof value used
+in the construction of the encryption and integrity values for the context. For session and sequence
+contexts, the hierarchy is TPM_RC_NULL. The hierarchy for a transient object may be TPM_RH_NULL
+but it is not required.
+14.7 Context Protection
+14.7.1 Context Integrity
+The integrity of the context blob is protected by an HMAC. The integrity value is constructed such that
+changes to the component values will invalidate the context and prevent it from being loaded.
+Previously saved contexts for objects in the Platform hierarchy shall not be loadable after the PPS is
+changed.
+Previously saved contexts for objects in the Storage hierarchy shall not be loadable after the SPS is
+changed.
+Previously saved contexts for objects in the Endorsement hierarchy shall not be loadable after either the
+EPS or SPS is changed.
+Previously saved sessions shall not be loadable after the SPS changes.
+Previously saved contexts for objects that have their stClear attribute SET shall not be loadable after a
+TPM Restart. If a Storage Key has its stClear attribute SET, the descendants of this key shall not be
+loadable after TPM Restart.
+Previously saved contexts for a session and objects shall not be loadable after a TPM Reset.
+A saved context shall not be loaded if its HMAC is not valid. The equation for computing the HMAC for a
+context is found in “Context Integrity Protection” in Part 1.
+14.7.2 Context Confidentiality
+The context data of sessions and objects shall be protected by symmetric encryption using CFB. The
+method for computing the IV and encryption key is found in “Context Confidentiality Protection” in Part 1.
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 143
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+15 Creation Data
+15.1 TPMS_CREATION_DATA
+This structure provides information relating to the creation environment for the object. The creation data
+includes the parent Name, parent Qualified Name, and the digest of selected PCR. These values
+represent the environment in which the object was created. Creation data allows a relying party to
+determine if an object was created when some appropriate protections were present.
+When the object is created, the structure shown in Table 204 is generated and a ticket is computed over
+this data.
+If
+the
+parent
+is
+a
+permanent
+handle
+(TPM_RH_OWNER,
+TPM_RH_PLATFORM,
+TPM_RH_ENDORSEMENT, or TPM_RH_NULL), then parentName and parentQualifiedName will be set
+to the parent handle value and parentNameAlg will be TPM_ALG_NULL.
+Table 204 — Definition of TPMS_CREATION_DATA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+pcrSelect
+
+TPML_PCR_SELECTION
+
+list indicating the PCR included in pcrDigest
+
+pcrDigest
+
+TPM2B_DIGEST
+
+digest of the selected PCR using nameAlg of the object for
+which this structure is being created
+pcrDigest.size shall be zero if the pcrSelect list is empty.
+
+locality
+
+TPMA_LOCALITY
+
+the locality at which the object was created
+
+parentNameAlg
+
+TPM_ALG_ID
+
+nameAlg of the parent
+
+parentName
+
+TPM2B_NAME
+
+Name of the parent at time of creation
+The size will match digest size associated with parentNameAlg
+unless it is TPM_ALG_NULL, in which case the size will be 4
+and parentName will be the hierarchy handle.
+
+parentQualifiedName
+
+TPM2B_NAME
+
+Qualified Name of the parent at the time of creation
+Size is the same as parentName.
+
+outsideInfo
+
+TPM2B_DATA
+
+association with additional information added by the key
+creator
+This will be the contents of the outsideInfo parameter in
+TPM2_Create() or TPM2_CreatePrimary().
+
+15.2 TPM2B_CREATION_DATA
+This structure is created by TPM2_Create() and TPM2_CreatePrimary(). It is never entered into the TPM
+and never has a size of zero.
+Table 205 — Definition of TPM2B_CREATION_DATA Structure <OUT>
+Parameter
+
+Type
+
+Description
+
+size=
+
+UINT16
+
+size of the creation data
+
+creationData
+
+TPMS_CREATION_DATA
+
+1.1.1.1.1
+Page 144
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Annex A
+(informative)
+Algorithm Constants
+A.1
+
+Introduction
+
+This annex contains constants that are defined by algorithms.
+
+A.2
+A.2.1
+
+Allowed Hash Algorithms
+SHA1
+Table 206 — Defines for SHA1 Hash Values
+
+Name
+
+Value
+
+SHA1_DIGEST_SIZE
+
+20
+
+SHA1_BLOCK_SIZE
+
+64
+
+SHA1_DER_SIZE
+
+Description
+
+15
+
+SHA1_DER
+
+Values are in octets.
+
+{0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}
+
+A.2.2
+
+SHA256
+Table 207 — Defines for SHA256 Hash Values
+
+Name
+
+Value
+
+SHA256_DIGEST_SIZE
+
+32
+
+SHA256_BLOCK_SIZE
+
+64
+
+SHA256_DER_SIZE
+
+Description
+
+19
+
+SHA256_DER
+
+
+Values are in octets.
+
+{0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}
+
+A.2.3
+SHA384
+Table 208 — Defines for SHA384 Hash Values
+
+Name
+
+Value
+
+SHA384_DIGEST_SIZE
+
+48
+
+SHA384_BLOCK_SIZE
+
+128
+
+SHA384_DER_SIZE
+
+Description
+
+19
+
+SHA384_DER
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Values are in octets.
+
+{0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30}
+
+Published
+Copyright © TCG 2006-2013
+
+Page 145
+October 31, 2013
+
+ Part 2: Structures
+A.2.4
+
+Trusted Platform Module Library
+
+SHA512
+Table 209 — Defines for SHA512 Hash Values
+
+Name
+
+Value
+
+SHA512_DIGEST_SIZE
+
+64
+
+SHA512_BLOCK_SIZE
+
+128
+
+SHA512_DER_SIZE
+
+Description
+
+19
+
+SHA512_DER
+
+
+Values are in octets.
+
+{0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40}
+
+A.2.5
+SM3_256
+Table 210 — Defines for SM3_256 Hash Values
+
+Name
+
+Value
+
+Description
+
+SM3_256_DIGEST_SIZE
+
+32
+
+Values are in octets.
+
+SM3_256_BLOCK_SIZE
+
+64
+
+??
+
+SM3_256_DER_SIZE
+
+18
+
+SM3_256_DER
+
+
+{0x30,0x30,0x30,0x0c,0x06,0x08,0x2a,0x81,0x1c,0x81,0x45,0x01,0x83,0x11,0x05,0x00,0x04,0x20}
+
+A.3
+Unknown
+
+Architectural Limits
+Table 211 — Defines for Architectural Limits Values
+
+Name
+MAX_SESSION_NUMBER
+
+Page 146
+October 31, 2013
+
+Value
+3
+
+Description
+the maximum number of authorization sessions that may be in a
+command
+This value may be increased if new commands require more than
+two authorization handles.
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Annex B
+(informative)
+Implementation Definitions
+B.1
+
+Introduction
+
+This annex contains some of the tables that are used to define the desired implementation for the
+automated tools.
+NOTE
+
+B.2
+
+The reference implementation assumes that stdint.h is used.
+
+Logic Values
+
+The values in this clause are used to see the generation of the subsequent tables. These values should
+not be changed.
+Table 212 — Defines for Logic Values
+Name
+
+Value
+
+YES
+
+1
+
+NO
+
+0
+
+TRUE
+
+1
+
+FALSE
+
+0
+
+SET
+
+1
+
+CLEAR
+
+Description
+
+0
+
+B.3
+
+Processor Values
+
+These values are used to control generation of octet-swapping routines. The canonical octet ordering for
+the TPM input/output buffer is “big endian” with the most significant octet of any datum at the lowest
+address.
+NOTE
+
+The setting for the exemplar is for the x86 family of processor.
+
+Table 213 — Defines for Processor Values
+Name
+
+Value
+
+Description
+
+BIG_ENDIAN_TPM
+
+NO
+
+set to YES or NO according to the processor
+
+LITTLE_ENDIAN_TPM
+
+YES
+
+set to YES or NO according to the processor
+NOTE
+
+NO_AUTO_ALIGN
+
+NO
+
+set to YES if the processor does not allow unaligned accesses
+NOTE
+
+Family “2.0”
+Level 00 Revision 00.99
+
+BIG_ENDIAN and LITTLE_ENDIAN shall be set to opposite values.
+
+If LITTLE_ENDIAN is YES, then the setting of this value has no effect.
+
+Published
+Copyright © TCG 2006-2013
+
+Page 147
+October 31, 2013
+
+ Part 2: Structures
+
+B.4
+
+Trusted Platform Module Library
+
+Implemented Algorithms
+
+Table 214 is used to indicate the algorithms that are implemented in a TPM. The selections in the Value
+column may be changed to reflect the implementation. The values shown are illustrative.
+The "Implemented" column contains a "Y", "YES", or blank to indicate that the command is present in the
+implementation, an "N" or "NO" to indicate that the command is not implemented.
+The leading and trailing “_” characters are to avoid name space collisions with some crypto libraries.
+
+NOTE
+
+Table 214 — Defines for Implemented Algorithms
+Algorithm Name
+
+Implemented
+
+RSA
+
+YES
+
+SHA1
+
+YES
+
+HMAC
+
+YES
+
+AES
+
+YES
+
+MGF1
+
+YES
+
+XOR
+
+YES
+
+KEYEDHASH
+
+YES
+
+SHA256
+
+YES
+
+SHA384
+
+NO
+
+SHA512
+
+NO
+
+SM3_256
+
+YES
+
+SM4
+
+Comments
+
+YES
+
+REQUIRED, do not change this value
+
+REQUIRED, do not change this value
+
+RSASSA
+
+(YES * RSA)
+
+requires RSA
+
+RSAES
+
+(YES * RSA)
+
+requires RSA
+
+RSAPSS
+
+(YES * RSA)
+
+requires RSA
+
+OAEP
+
+(YES * RSA)
+
+requires RSA
+
+ECC
+
+YES
+
+ECDH
+
+(YES * ECC)
+
+requires ECC
+
+ECDSA
+
+(YES * ECC)
+
+requires ECC
+
+ECDAA
+
+(YES * ECC)
+
+requires ECC
+
+SM2
+
+(YES * ECC)
+
+requires ECC
+
+ECSCHNORR
+
+(YES * ECC)
+
+requires ECC
+
+ECMQV
+
+(NO * ECC)
+
+requires ECC
+
+SYMCIPHER
+KDF1_SP800_56a
+
+YES
+
+REQUIRED, at least one symmetric algorithm shall be implemented
+
+(YES * ECC)
+
+KDF2
+
+NO
+
+KDF1_SP800_108
+
+YES
+
+CTR
+
+YES
+
+OFB
+
+YES
+
+CBC
+
+YES
+
+CFB
+
+YES
+
+ECB
+
+requires ECC
+
+YES
+
+B.5
+
+REQUIRED, do not change this value
+
+Implemented Commands
+
+Page 148
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+This table is used to indicate which of the commands are implemented. In the reference implementation,
+this table determines which commands can be called and drives the generation of various commanddependent switch statements.
+The "Implemented or Dependent" column contains a "Y", "YES", or blank to indicate that the command is
+present in the implementation; an "N" or "NO" to indicate that the command is not implemented; and an
+algorithm value if implementation of the command is dependent on a setting in Table 214. Linkage to
+Table 214 is not required and is provide as a convenience.
+To indicate that the command is implemented, only "Y", "N", blank, or a value from Table 214 is allowed.
+Table 215 — Defines for Implemented Commands
+Name
+ActivateCredential
+
+Implemented
+or Dependent
+
+Comments
+
+YES
+
+Certify
+
+Y
+
+CertifyCreation
+
+Y
+
+ChangeEPS
+
+Y
+
+ChangePPS
+
+Y
+
+Clear
+
+Y
+
+ClearControl
+
+Y
+
+ClockRateAdjust
+
+Y
+
+ClockSet
+
+Y
+
+Commit
+
+ECC
+
+ContextLoad
+
+Y
+
+Context
+
+ContextSave
+
+Y
+
+Context
+
+Create
+
+Y
+
+CreatePrimary
+
+Y
+
+DictionaryAttackLockReset
+
+Y
+
+DictionaryAttackParameters
+
+Y
+
+Duplicate
+
+Y
+
+ECC_Parameters
+
+ECC
+
+ECDH_KeyGen
+
+ECC
+
+ECDH_ZGen
+
+ECC
+
+EncryptDecrypt
+
+Y
+
+EventSequenceComplete
+
+Y
+
+EvictControl
+
+Y
+
+FieldUpgradeData
+
+N
+
+FieldUpgradeStart
+
+N
+
+FirmwareRead
+
+N
+
+FlushContext
+
+Y
+
+GetCapability
+
+Y
+
+GetCommandAuditDigest
+
+Y
+
+GetRandom
+
+Y
+
+GetSessionAuditDigest
+
+Y
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Context
+
+Published
+Copyright © TCG 2006-2013
+
+Page 149
+October 31, 2013
+
+ Part 2: Structures
+
+Name
+
+Trusted Platform Module Library
+Implemented
+or Dependent
+
+Comments
+
+GetTestResult
+
+Y
+
+GetTime
+
+Y
+
+Hash
+
+Y
+
+HashSequenceStart
+
+Y
+
+HierarchyChangeAuth
+
+Y
+
+HierarchyControl
+
+Y
+
+HMAC
+
+Y
+
+HMAC_Start
+
+Y
+
+Import
+
+Y
+
+IncrementalSelfTest
+
+Y
+
+Load
+
+Y
+
+LoadExternal
+
+Y
+
+MakeCredential
+
+Y
+
+NV_Certify
+
+Y
+
+NV_ChangeAuth
+
+Y
+
+NV_DefineSpace
+
+Y
+
+NV_Extend
+
+Y
+
+NV_GlobalWriteLock
+
+Y
+
+NV_Increment
+
+Y
+
+NV_Read
+
+Y
+
+NV_ReadLock
+
+Y
+
+NV_ReadPublic
+
+Y
+
+NV_SetBits
+
+Y
+
+NV_UndefineSpace
+
+Y
+
+NV_UndefineSpaceSpecial
+
+Y
+
+NV_Write
+
+Y
+
+NV_WriteLock
+
+Y
+
+ObjectChangeAuth
+
+Y
+
+PCR_Allocate
+
+Y
+
+PCR_Event
+
+Y
+
+PCR_Extend
+
+Y
+
+PCR_Read
+
+Y
+
+PCR
+
+PCR_Reset
+
+Y
+
+PCR
+
+PCR_SetAuthPolicy
+
+Y
+
+PCR_SetAuthValue
+
+Y
+
+PolicyAuthorize
+
+Y
+
+Policy
+
+PolicyAuthValue
+
+Y
+
+Policy
+
+PolicyCommandCode
+
+Y
+
+Policy
+
+PolicyCounterTimer
+
+Y
+
+Policy
+
+PolicyCpHash
+
+Y
+
+Policy
+
+Page 150
+October 31, 2013
+
+NV
+
+PCR
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+Implemented
+or Dependent
+
+Name
+
+Comments
+
+PolicyDuplicationSelect
+
+Y
+
+Policy
+
+PolicyGetDigest
+
+Y
+
+Policy
+
+PolicyLocality
+
+Y
+
+Policy
+
+PolicyNameHash
+
+Y
+
+Policy
+
+PolicyNV
+
+Y
+
+Policy
+
+PolicyOR
+
+Y
+
+Policy
+
+PolicyPassword
+
+Y
+
+Policy
+
+PolicyPCR
+
+Y
+
+Policy
+
+PolicyPhysicalPresence
+
+Y
+
+Policy
+
+PolicyRestart
+
+Y
+
+PolicySecret
+
+Y
+
+Policy
+
+PolicySigned
+
+Y
+
+Policy
+
+PolicyTicket
+
+Y
+
+Policy
+
+PP_Commands
+
+Y
+
+Quote
+
+Y
+
+ReadClock
+
+Y
+
+ReadPublic
+
+Y
+
+Rewrap
+
+Y
+
+RSA_Decrypt
+
+RSA
+
+RSA_Encrypt
+
+RSA
+
+SelfTest
+
+Y
+
+SequenceComplete
+
+Y
+
+SequenceUpdate
+
+Y
+
+SetAlgorithmSet
+
+Y
+
+SetCommandCodeAuditStatus
+
+Y
+
+SetPrimaryPolicy
+
+Y
+
+Shutdown
+
+Y
+
+Sign
+
+Y
+
+StartAuthSession
+
+Y
+
+Startup
+
+Y
+
+StirRandom
+
+Y
+
+TestParms
+
+Y
+
+Unseal
+
+Y
+
+VerifySignature
+
+Y
+
+ZGen_2Phase
+
+Y
+
+EC_Ephemeral
+
+Y
+
+PolicyNvWritten
+
+Y
+
+B.6
+
+Algorithm Constants
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 151
+October 31, 2013
+
+ Part 2: Structures
+B.6.1
+
+Trusted Platform Module Library
+
+RSA
+Table 216 — Defines for RSA Algorithm Constants
+
+Name
+
+Value
+
+Comments
+
+RSA_KEY_SIZES_BITS
+
+{1024, 2048}
+
+braces because this is a
+list value
+
+MAX_RSA_KEY_BITS
+
+2048
+
+MAX_RSA_KEY_BYTES
+
+((MAX_RSA_KEY_BITS + 7) / 8)
+
+B.6.2
+
+ECC
+Table 217 — Defines for ECC Algorithm Constants
+
+Name
+
+Value
+
+ECC_CURVES
+
+{TPM_ECC_NIST_P256, TPM_ECC_BN_P256, TPM_ECC_SM2_P256}
+
+ECC_KEY_SIZES_BITS
+
+{256}
+
+MAX_ECC_KEY_BITS
+
+256
+
+MAX_ECC_KEY_BYTES
+
+((MAX_ECC_KEY_BITS + 7) / 8)
+
+B.6.3
+
+Comments
+
+this is a list value with
+length of one
+
+AES
+Table 218 — Defines for AES Algorithm Constants
+
+Name
+
+Value
+
+AES_KEY_SIZES_BITS
+
+{128}
+
+MAX_AES_KEY_BITS
+
+128
+
+MAX_AES_BLOCK_SIZE_BYTES
+
+16
+
+MAX_AES_KEY_BYTES
+
+((MAX_AES_KEY_BITS + 7) / 8)
+
+B.6.4
+
+Comments
+
+SM4
+Table 219 — Defines for SM4 Algorithm Constants
+
+Name
+
+Value
+
+SM4_KEY_SIZES_BITS
+
+{128}
+
+MAX_SM4_KEY_BITS
+
+128
+
+MAX_SM4_BLOCK_SIZE_BYTES
+
+16
+
+MAX_SM4_KEY_BYTES
+
+((MAX_SM4_KEY_BITS + 7) / 8)
+
+Page 152
+October 31, 2013
+
+Comments
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+B.6.5
+
+Part 2: Structures
+
+Symmetric
+
+The definitions in this table are derived from the implemented symmetric algorithms.
+Table 220 — Defines for Symmetric Algorithm Constants
+Name
+
+Value
+
+MAX_SYM_KEY_BITS
+
+MAX_AES_KEY_BITS
+
+MAX_SYM_KEY_BYTES
+
+MAX_AES_KEY_BYTES
+
+MAX_SYM_BLOCK_SIZE
+
+MAX_AES_BLOCK_SIZE_BYTES
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Comments
+
+Published
+Copyright © TCG 2006-2013
+
+Page 153
+October 31, 2013
+
+ Part 2: Structures
+
+B.7
+
+Trusted Platform Module Library
+
+Implementation Specific Values
+
+The values listed in Table 221 are defined for a specific TPM implementation. The numbers in the Value
+column may be changed to reflect the implementation. The values shown are illustrative.
+Table 221 — Defines for Implementation Values
+Name
+
+Value
+
+Description
+
+FIELD_UPGRADE_IMPLEMENTED
+
+NO
+
+temporary define
+
+BSIZE
+
+UINT16
+
+size used for internal storage of
+the size field of a TPM2B
+This is the definition used for
+the reference design.
+Compilation with this value
+changed may cause warnings
+about conversions.
+
+BUFFER_ALIGNMENT
+
+4
+
+sets the size granularity for the
+buffers in a TPM2B structure
+TPMxB buffers will be assigned
+a space that is a multiple of this
+value. This does not set the size
+limits for IO. Those are set by
+the canonical form of the
+TPMxB
+
+IMPLEMENTATION_PCR
+
+24
+
+the number of PCR in the TPM
+
+PLATFORM_PCR
+
+24
+
+the number of PCR required by
+the relevant platform
+specification
+
+DRTM_PCR
+
+17
+
+the DRTM PCR
+
+HCRTM_PCR
+
+0
+
+the PCR that will receive the HCRTM value at TPM2_Startup
+
+NUM_LOCALITIES
+
+5
+
+the number of localities
+supported by the TPM
+This is expected to be either 5
+for a PC, or 1 for just about
+everything else.
+
+MAX_HANDLE_NUM
+
+3
+
+the maximum number of
+handles in the handle area
+This should be produced by the
+Part 3 parser but is here for
+now.
+
+MAX_ACTIVE_SESSIONS
+
+64
+
+the number of simultaneously
+active sessions that are
+supported by the TPM
+implementation
+
+CONTEXT_SLOT
+
+UINT16
+
+the type of an entry in the array
+of saved contexts
+
+CONTEXT_COUNTER
+
+UINT64
+
+the type of the saved session
+counter
+
+MAX_LOADED_SESSIONS
+
+3
+
+the number of sessions that the
+TPM may have in memory
+
+MAX_SESSION_NUM
+
+3
+
+this is the current maximum
+value
+
+Page 154
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+ Trusted Platform Module Library
+
+Part 2: Structures
+
+Name
+
+Value
+
+Description
+
+MAX_LOADED_OBJECTS
+
+3
+
+the number of simultaneously
+loaded objects that are
+supported by the TPM; this
+number does not include the
+objects that may be placed in
+NV memory by
+TPM2_EvictControl().
+
+MIN_EVICT_OBJECTS
+
+2
+
+the minimum number of evict
+objects supported by the TPM
+
+PCR_SELECT_MIN
+
+((PLATFORM_PCR+7)/8)
+
+PCR_SELECT_MAX
+
+((IMPLEMENTATION_PCR+7)/8)
+
+NUM_POLICY_PCR_GROUP
+
+1
+
+number of PCR groups that
+have individual policies
+
+NUM_AUTHVALUE_PCR_GROUP
+
+1
+
+number of PCR groups that
+have individual authorization
+values
+
+MAX_CONTEXT_SIZE
+
+4000
+
+This may be larger than
+necessary
+
+MAX_DIGEST_BUFFER
+
+1024
+
+MAX_NV_INDEX_SIZE
+
+2048
+
+maximum data size allowed in
+an NV Index
+
+MAX_NV_BUFFER_SIZE
+
+1024
+
+maximum data size in one NV
+read or write command
+
+MAX_CAP_BUFFER
+
+1024
+
+NV_MEMORY_SIZE
+
+16384
+
+NUM_STATIC_PCR
+
+16
+
+MAX_ALG_LIST_SIZE
+
+64
+
+number of algorithms that can
+be in a list
+
+TIMER_PRESCALE
+
+100000
+
+nominal value for the pre-scale
+value of Clock (the number of
+cycles of the TPM's oscillator for
+each increment of Clock)
+
+PRIMARY_SEED_SIZE
+
+32
+
+size of the Primary Seed in
+octets
+
+CONTEXT_ENCRYPT_ALG
+
+TPM_ALG_AES
+
+context encryption algorithm
+
+CONTEXT_ENCRYPT_KEY_BITS
+
+MAX_SYM_KEY_BITS
+
+context encryption key size in
+bits
+
+CONTEXT_ENCRYPT_KEY_BYTES
+
+((CONTEXT_ENCRYPT_KEY_BITS+7)/8)
+
+CONTEXT_INTEGRITY_HASH_ALG
+
+TPM_ALG_SHA256
+
+context integrity hash algorithm
+
+CONTEXT_INTEGRITY_HASH_SIZE
+
+SHA256_DIGEST_SIZE
+
+number of byes in the context
+integrity digest
+
+PROOF_SIZE
+
+CONTEXT_INTEGRITY_HASH_SIZE
+
+size of proof value in octets
+This size of the proof should be
+consistent with the digest size
+used for context integrity.
+
+NV_CLOCK_UPDATE_INTERVAL
+
+12
+
+the update interval expressed
+as a power of 2 seconds
+
+size of NV memory in octets
+
+A value of 12 is 4,096 seconds
+(~68 minutes).
+
+Family “2.0”
+Level 00 Revision 00.99
+
+Published
+Copyright © TCG 2006-2013
+
+Page 155
+October 31, 2013
+
+ Part 2: Structures
+
+Trusted Platform Module Library
+
+Name
+
+Value
+
+Description
+
+NUM_POLICY_PCR
+
+1
+
+number of PCR that allow
+policy/auth
+
+MAX_COMMAND_SIZE
+
+4096
+
+maximum size of a command
+
+MAX_RESPONSE_SIZE
+
+4096
+
+maximum size of a response
+
+ORDERLY_BITS
+
+8
+
+number between 1 and 32
+inclusive
+
+MAX_ORDERLY_COUNT
+
+((1 << ORDERLY_BITS) - 1)
+
+maximum count of orderly
+counter before NV is updated
+This must be of the form 2N – 1
+where 1 ≤ N ≤ 32.
+
+ALG_ID_FIRST
+
+TPM_ALG_FIRST
+
+used by GetCapability()
+processing to bound the
+algorithm search
+
+ALG_ID_LAST
+
+TPM_ALG_LAST
+
+used by GetCapability()
+processing to bound the
+algorithm search
+
+MAX_SYM_DATA
+
+128
+
+this is the maximum number of
+octets that may be in a sealed
+blob.
+
+MAX_RNG_ENTROPY_SIZE
+
+64
+
+RAM_INDEX_SPACE
+
+512
+
+RSA_DEFAULT_PUBLIC_EXPONENT
+
+0x00010001
+
+216 + 1
+
+ENABLE_PCR_NO_INCREMENT
+
+YES
+
+
+CRT_FORMAT_RSA
+
+YES
+
+PRIVATE_VENDOR_SPECIFIC_BYTES
+
+((MAX_RSA_KEY_BYTES/2) * (3 + CRT_FORMAT_RSA * 2))
+
+Page 156
+October 31, 2013
+
+Published
+Copyright © TCG 2006-2013
+
+Family “2.0”
+Level 00 Revision 00.99
+
+
diff --git a/trunks/generator/union_selectors.py b/trunks/generator/union_selectors.py
new file mode 100644
index 0000000..661cfe5
--- /dev/null
+++ b/trunks/generator/union_selectors.py
@@ -0,0 +1,192 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+"""Provides selector information for TPM 2.0 unions.
+
+Describing this information explicitly is easier than extracting it from the
+specification.
+"""
+
+_SELECTORS = {
+ 'TPMU_HA': {
+ 'type': ['TPMI_ALG_HASH'],
+ 'selectors': {
+ 'TPM_ALG_SHA1': 'sha1[SHA1_DIGEST_SIZE]',
+ 'TPM_ALG_SHA256': 'sha256[SHA256_DIGEST_SIZE]',
+ 'TPM_ALG_SM3_256': 'sm3_256[SM3_256_DIGEST_SIZE]',
+ 'TPM_ALG_SHA384': 'sha384[SHA384_DIGEST_SIZE]',
+ 'TPM_ALG_SHA512': 'sha512[SHA512_DIGEST_SIZE]',
+ 'TPM_ALG_NULL': ''
+ }
+ },
+ 'TPMU_CAPABILITIES': {
+ 'type': ['TPM_CAP'],
+ 'selectors': {
+ 'TPM_CAP_ALGS': 'algorithms',
+ 'TPM_CAP_HANDLES': 'handles',
+ 'TPM_CAP_COMMANDS': 'command',
+ 'TPM_CAP_PP_COMMANDS': 'ppCommands',
+ 'TPM_CAP_AUDIT_COMMANDS': 'auditCommands',
+ 'TPM_CAP_PCRS': 'assignedPCR',
+ 'TPM_CAP_TPM_PROPERTIES': 'tpmProperties',
+ 'TPM_CAP_PCR_PROPERTIES': 'pcrProperties',
+ 'TPM_CAP_ECC_CURVES': 'eccCurves',
+ }
+ },
+ 'TPMU_ATTEST': {
+ 'type': ['TPMI_ST_ATTEST'],
+ 'selectors': {
+ 'TPM_ST_ATTEST_CERTIFY': 'certify',
+ 'TPM_ST_ATTEST_CREATION': 'creation',
+ 'TPM_ST_ATTEST_QUOTE': 'quote',
+ 'TPM_ST_ATTEST_COMMAND_AUDIT': 'commandAudit',
+ 'TPM_ST_ATTEST_SESSION_AUDIT': 'sessionAudit',
+ 'TPM_ST_ATTEST_TIME': 'time',
+ 'TPM_ST_ATTEST_NV': 'nv',
+ }
+ },
+ 'TPMU_SYM_KEY_BITS': {
+ 'type': ['TPMI_ALG_SYM', 'TPMI_ALG_SYM_OBJECT'],
+ 'selectors': {
+ 'TPM_ALG_AES': 'aes',
+ 'TPM_ALG_SM4': 'SM4',
+ 'TPM_ALG_XOR': 'xor_',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_SYM_MODE': {
+ 'type': ['TPMI_ALG_SYM', 'TPMI_ALG_SYM_OBJECT'],
+ 'selectors': {
+ 'TPM_ALG_AES': 'aes',
+ 'TPM_ALG_SM4': 'SM4',
+ 'TPM_ALG_XOR': '',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_SYM_DETAILS': {
+ 'type': ['TPMI_ALG_SYM', 'TPMI_ALG_SYM_OBJECT'],
+ 'selectors': {}
+ },
+ 'TPMU_SCHEME_KEYEDHASH': {
+ 'type': ['TPMI_ALG_KEYEDHASH_SCHEME'],
+ 'selectors': {
+ 'TPM_ALG_HMAC': 'hmac',
+ 'TPM_ALG_XOR': 'xor_',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_SIG_SCHEME': {
+ 'type': ['TPMI_ALG_SIG_SCHEME', 'TPMI_ALG_ECC_SCHEME'],
+ 'selectors': {
+ 'TPM_ALG_RSASSA': 'rsassa',
+ 'TPM_ALG_RSAPSS': 'rsapss',
+ 'TPM_ALG_ECDSA': 'ecdsa',
+ 'TPM_ALG_SM2': 'sm2',
+ 'TPM_ALG_ECDAA': 'ecdaa',
+ 'TPM_ALG_ECSCHNORR': 'ecSchnorr',
+ 'TPM_ALG_HMAC': 'hmac',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_KDF_SCHEME': {
+ 'type': ['TPMI_ALG_KDF'],
+ 'selectors': {
+ 'TPM_ALG_MGF1': 'mgf1',
+ 'TPM_ALG_KDF1_SP800_56a': 'kdf1_SP800_56a',
+ 'TPM_ALG_KDF2': 'kdf2',
+ 'TPM_ALG_KDF1_SP800_108': 'kdf1_sp800_108',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_ASYM_SCHEME': {
+ 'type': ['TPMI_ALG_ASYM_SCHEME',
+ 'TPMI_ALG_RSA_SCHEME',
+ 'TPMI_ALG_RSA_DECRYPT',
+ 'TPMI_ALG_ECC_SCHEME'],
+ 'selectors': {
+ 'TPM_ALG_RSASSA': 'rsassa',
+ 'TPM_ALG_RSAPSS': 'rsapss',
+ 'TPM_ALG_RSAES': '',
+ 'TPM_ALG_OAEP': 'oaep',
+ 'TPM_ALG_ECDSA': 'ecdsa',
+ 'TPM_ALG_SM2': 'sm2',
+ 'TPM_ALG_ECDAA': 'ecdaa',
+ 'TPM_ALG_ECSCHNORR': 'ecSchnorr',
+ 'TPM_ALG_ECDH': 'ecdh',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_SIGNATURE': {
+ 'type': ['TPMI_ALG_SIG_SCHEME'],
+ 'selectors': {
+ 'TPM_ALG_RSASSA': 'rsassa',
+ 'TPM_ALG_RSAPSS': 'rsapss',
+ 'TPM_ALG_ECDSA': 'ecdsa',
+ 'TPM_ALG_SM2': 'sm2',
+ 'TPM_ALG_ECDAA': 'ecdaa',
+ 'TPM_ALG_ECSCHNORR': 'ecschnorr',
+ 'TPM_ALG_HMAC': 'hmac',
+ 'TPM_ALG_NULL': '',
+ }
+ },
+ 'TPMU_PUBLIC_PARMS': {
+ 'type': ['TPMI_ALG_PUBLIC'],
+ 'selectors': {
+ 'TPM_ALG_KEYEDHASH': 'keyedHashDetail',
+ 'TPM_ALG_SYMCIPHER': 'symDetail',
+ 'TPM_ALG_RSA': 'rsaDetail',
+ 'TPM_ALG_ECC': 'eccDetail',
+ }
+ },
+ 'TPMU_PUBLIC_ID': {
+ 'type': ['TPMI_ALG_PUBLIC'],
+ 'selectors': {
+ 'TPM_ALG_KEYEDHASH': 'keyedHash',
+ 'TPM_ALG_SYMCIPHER': 'sym',
+ 'TPM_ALG_RSA': 'rsa',
+ 'TPM_ALG_ECC': 'ecc',
+ }
+ },
+ 'TPMU_SENSITIVE_COMPOSITE': {
+ 'type': ['TPMI_ALG_PUBLIC'],
+ 'selectors': {
+ 'TPM_ALG_KEYEDHASH': 'bits',
+ 'TPM_ALG_SYMCIPHER': 'sym',
+ 'TPM_ALG_RSA': 'rsa',
+ 'TPM_ALG_ECC': 'ecc',
+ }
+ },
+}
+
+
+def GetUnionSelectorType(union_type):
+ """Returns the selector type for a given union."""
+ return _SELECTORS[union_type]['type'][0]
+
+
+def GetUnionSelectorTypes(union_type):
+ """Returns a list of all acceptable selector types for a given union."""
+ return _SELECTORS[union_type]['type']
+
+
+def GetUnionSelectorValues(union_type):
+ """Returns the list of possible selector values for a given union."""
+ return _SELECTORS[union_type]['selectors'].keys()
+
+
+def GetUnionSelectorField(union_type, selector_value):
+ """Returns the union field associated with a given selector value."""
+ return _SELECTORS[union_type]['selectors'][selector_value]
diff --git a/trunks/hmac_authorization_delegate.cc b/trunks/hmac_authorization_delegate.cc
new file mode 100644
index 0000000..5aa842b
--- /dev/null
+++ b/trunks/hmac_authorization_delegate.cc
@@ -0,0 +1,325 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/hmac_authorization_delegate.h"
+
+#include <base/logging.h>
+#include <base/memory/scoped_ptr.h>
+#include <base/stl_util.h>
+#include <crypto/secure_util.h>
+#include <openssl/aes.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+
+namespace trunks {
+
+namespace {
+
+const uint32_t kDigestBits = 256;
+const uint16_t kNonceMinSize = 16;
+const uint16_t kNonceMaxSize = 32;
+const uint8_t kDecryptSession = 1<<5;
+const uint8_t kEncryptSession = 1<<6;
+const uint8_t kLabelSize = 4;
+const size_t kAesIVSize = 16;
+const uint32_t kTpmBufferSize = 4096;
+
+} // namespace
+
+HmacAuthorizationDelegate::HmacAuthorizationDelegate()
+ : session_handle_(0),
+ is_parameter_encryption_enabled_(false),
+ nonce_generated_(false),
+ future_authorization_value_set_(false),
+ use_entity_authorization_for_encryption_only_(false) {
+ tpm_nonce_.size = 0;
+ caller_nonce_.size = 0;
+}
+
+HmacAuthorizationDelegate::~HmacAuthorizationDelegate() {}
+
+bool HmacAuthorizationDelegate::GetCommandAuthorization(
+ const std::string& command_hash,
+ bool is_command_parameter_encryption_possible,
+ bool is_response_parameter_encryption_possible,
+ std::string* authorization) {
+ if (!session_handle_) {
+ authorization->clear();
+ LOG(ERROR) << "Delegate being used before Initialization,";
+ return false;
+ }
+ TPMS_AUTH_COMMAND auth;
+ auth.session_handle = session_handle_;
+ if (!nonce_generated_) {
+ RegenerateCallerNonce();
+ }
+ auth.nonce = caller_nonce_;
+ auth.session_attributes = kContinueSession;
+ if (is_parameter_encryption_enabled_) {
+ if (is_command_parameter_encryption_possible) {
+ auth.session_attributes |= kDecryptSession;
+ }
+ if (is_response_parameter_encryption_possible) {
+ auth.session_attributes |= kEncryptSession;
+ }
+ }
+ // We reset the |nonce_generated| flag in preperation of the next command.
+ nonce_generated_ = false;
+ std::string attributes_bytes;
+ CHECK_EQ(Serialize_TPMA_SESSION(auth.session_attributes, &attributes_bytes),
+ TPM_RC_SUCCESS) << "Error serializing session attributes.";
+
+ std::string hmac_data;
+ std::string hmac_key;
+ if (!use_entity_authorization_for_encryption_only_) {
+ hmac_key = session_key_ + entity_authorization_value_;
+ } else {
+ hmac_key = session_key_;
+ }
+ hmac_data.append(command_hash);
+ hmac_data.append(reinterpret_cast<const char*>(caller_nonce_.buffer),
+ caller_nonce_.size);
+ hmac_data.append(reinterpret_cast<const char*>(tpm_nonce_.buffer),
+ tpm_nonce_.size);
+ hmac_data.append(attributes_bytes);
+ std::string digest = HmacSha256(hmac_key, hmac_data);
+ auth.hmac = Make_TPM2B_DIGEST(digest);
+
+ TPM_RC serialize_error = Serialize_TPMS_AUTH_COMMAND(auth, authorization);
+ if (serialize_error != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Could not serialize command auth.";
+ return false;
+ }
+ return true;
+}
+
+bool HmacAuthorizationDelegate::CheckResponseAuthorization(
+ const std::string& response_hash,
+ const std::string& authorization) {
+ if (!session_handle_) {
+ return false;
+ }
+ TPMS_AUTH_RESPONSE auth_response;
+ std::string mutable_auth_string(authorization);
+ TPM_RC parse_error;
+ parse_error = Parse_TPMS_AUTH_RESPONSE(&mutable_auth_string,
+ &auth_response,
+ nullptr);
+ if (parse_error != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Could not parse authorization response.";
+ return false;
+ }
+ if (auth_response.hmac.size != kHashDigestSize) {
+ LOG(ERROR) << "TPM auth hmac was incorrect size.";
+ return false;
+ }
+ if (auth_response.nonce.size < kNonceMinSize ||
+ auth_response.nonce.size > kNonceMaxSize) {
+ LOG(ERROR) << "TPM_nonce is not the correct length.";
+ return false;
+ }
+ tpm_nonce_ = auth_response.nonce;
+ std::string attributes_bytes;
+ CHECK_EQ(Serialize_TPMA_SESSION(auth_response.session_attributes,
+ &attributes_bytes),
+ TPM_RC_SUCCESS) << "Error serializing session attributes.";
+
+ std::string hmac_data;
+ std::string hmac_key;
+ if (!use_entity_authorization_for_encryption_only_) {
+ // In a special case with TPM2_HierarchyChangeAuth, we need to use the
+ // auth_value that was set.
+ if (future_authorization_value_set_) {
+ hmac_key = session_key_ + future_authorization_value_;
+ future_authorization_value_set_ = false;
+ } else {
+ hmac_key = session_key_ + entity_authorization_value_;
+ }
+ } else {
+ hmac_key = session_key_;
+ }
+ hmac_data.append(response_hash);
+ hmac_data.append(reinterpret_cast<const char*>(tpm_nonce_.buffer),
+ tpm_nonce_.size);
+ hmac_data.append(reinterpret_cast<const char*>(caller_nonce_.buffer),
+ caller_nonce_.size);
+ hmac_data.append(attributes_bytes);
+ std::string digest = HmacSha256(hmac_key, hmac_data);
+ CHECK_EQ(digest.size(), auth_response.hmac.size);
+ if (!crypto::SecureMemEqual(digest.data(), auth_response.hmac.buffer,
+ digest.size())) {
+ LOG(ERROR) << "Authorization response hash did not match expected value.";
+ return false;
+ }
+ return true;
+}
+
+bool HmacAuthorizationDelegate::EncryptCommandParameter(
+ std::string* parameter) {
+ CHECK(parameter);
+ if (!session_handle_) {
+ LOG(ERROR) << __func__ << ": Invalid session handle.";
+ return false;
+ }
+ if (!is_parameter_encryption_enabled_) {
+ // No parameter encryption enabled.
+ return true;
+ }
+ if (parameter->size() > kTpmBufferSize) {
+ LOG(ERROR) << "Parameter size is too large for TPM decryption.";
+ return false;
+ }
+ RegenerateCallerNonce();
+ nonce_generated_ = true;
+ AesOperation(parameter, caller_nonce_, tpm_nonce_, AES_ENCRYPT);
+ return true;
+}
+
+bool HmacAuthorizationDelegate::DecryptResponseParameter(
+ std::string* parameter) {
+ CHECK(parameter);
+ if (!session_handle_) {
+ LOG(ERROR) << __func__ << ": Invalid session handle.";
+ return false;
+ }
+ if (!is_parameter_encryption_enabled_) {
+ // No parameter decryption enabled.
+ return true;
+ }
+ if (parameter->size() > kTpmBufferSize) {
+ LOG(ERROR) << "Parameter size is too large for TPM encryption.";
+ return false;
+ }
+ AesOperation(parameter, tpm_nonce_, caller_nonce_, AES_DECRYPT);
+ return true;
+}
+
+bool HmacAuthorizationDelegate::InitSession(
+ TPM_HANDLE session_handle,
+ const TPM2B_NONCE& tpm_nonce,
+ const TPM2B_NONCE& caller_nonce,
+ const std::string& salt,
+ const std::string& bind_auth_value,
+ bool enable_parameter_encryption) {
+ session_handle_ = session_handle;
+ if (caller_nonce.size < kNonceMinSize || caller_nonce.size > kNonceMaxSize ||
+ tpm_nonce.size < kNonceMinSize || tpm_nonce.size > kNonceMaxSize) {
+ LOG(INFO) << "Session Nonces have to be between 16 and 32 bytes long.";
+ return false;
+ }
+ tpm_nonce_ = tpm_nonce;
+ caller_nonce_ = caller_nonce;
+ std::string session_key_label("ATH", kLabelSize);
+ is_parameter_encryption_enabled_ = enable_parameter_encryption;
+ if (salt.length() == 0 && bind_auth_value.length() == 0) {
+ // SessionKey is set to the empty string for unsalted and
+ // unbound sessions.
+ session_key_ = std::string();
+ } else {
+ session_key_ = CreateKey(bind_auth_value + salt,
+ session_key_label,
+ tpm_nonce_,
+ caller_nonce_);
+ }
+ return true;
+}
+
+void HmacAuthorizationDelegate::set_future_authorization_value(
+ const std::string& auth_value) {
+ future_authorization_value_ = auth_value;
+ future_authorization_value_set_ = true;
+}
+
+std::string HmacAuthorizationDelegate::CreateKey(
+ const std::string& hmac_key,
+ const std::string& label,
+ const TPM2B_NONCE& nonce_newer,
+ const TPM2B_NONCE& nonce_older) {
+ std::string counter;
+ std::string digest_size_bits;
+ if (Serialize_uint32_t(1, &counter) != TPM_RC_SUCCESS ||
+ Serialize_uint32_t(kDigestBits, &digest_size_bits) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing uint32_t during session key generation.";
+ return std::string();
+ }
+ CHECK_EQ(counter.size(), sizeof(uint32_t));
+ CHECK_EQ(digest_size_bits.size(), sizeof(uint32_t));
+ CHECK_EQ(label.size(), kLabelSize);
+
+ std::string data;
+ data.append(counter);
+ data.append(label);
+ data.append(reinterpret_cast<const char*>(nonce_newer.buffer),
+ nonce_newer.size);
+ data.append(reinterpret_cast<const char*>(nonce_older.buffer),
+ nonce_older.size);
+ data.append(digest_size_bits);
+ std::string key = HmacSha256(hmac_key, data);
+ return key;
+}
+
+std::string HmacAuthorizationDelegate::HmacSha256(const std::string& key,
+ const std::string& data) {
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int digest_length;
+ HMAC(EVP_sha256(),
+ key.data(),
+ key.size(),
+ reinterpret_cast<const unsigned char*>(data.data()),
+ data.size(),
+ digest,
+ &digest_length);
+ CHECK_EQ(digest_length, kHashDigestSize);
+ return std::string(reinterpret_cast<char*>(digest), digest_length);
+}
+
+void HmacAuthorizationDelegate::AesOperation(std::string* parameter,
+ const TPM2B_NONCE& nonce_newer,
+ const TPM2B_NONCE& nonce_older,
+ int operation_type) {
+ std::string label("CFB", kLabelSize);
+ std::string compound_key = CreateKey(
+ session_key_ + entity_authorization_value_,
+ label,
+ nonce_newer,
+ nonce_older);
+ CHECK_EQ(compound_key.size(), kAesKeySize + kAesIVSize);
+ unsigned char aes_key[kAesKeySize];
+ unsigned char aes_iv[kAesIVSize];
+ memcpy(aes_key, &compound_key[0], kAesKeySize);
+ memcpy(aes_iv, &compound_key[kAesKeySize], kAesIVSize);
+ AES_KEY key;
+ int iv_offset = 0;
+ AES_set_encrypt_key(aes_key, kAesKeySize*8, &key);
+ unsigned char decrypted[kTpmBufferSize];
+ AES_cfb128_encrypt(reinterpret_cast<const unsigned char*>(parameter->data()),
+ decrypted,
+ parameter->size(),
+ &key, aes_iv,
+ &iv_offset,
+ operation_type);
+ memcpy(string_as_array(parameter), decrypted, parameter->size());
+}
+
+void HmacAuthorizationDelegate::RegenerateCallerNonce() {
+ CHECK(session_handle_);
+ // RAND_bytes takes a signed number, but since nonce_size is guaranteed to be
+ // less than 32 bytes and greater than 16 we dont have to worry about it.
+ CHECK_EQ(RAND_bytes(caller_nonce_.buffer, caller_nonce_.size), 1) <<
+ "Error regnerating a cryptographically random nonce.";
+}
+
+} // namespace trunks
diff --git a/trunks/hmac_authorization_delegate.h b/trunks/hmac_authorization_delegate.h
new file mode 100644
index 0000000..2a02827
--- /dev/null
+++ b/trunks/hmac_authorization_delegate.h
@@ -0,0 +1,164 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
+#define TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
+
+#include <string>
+
+#include <base/gtest_prod_util.h>
+#include <crypto/secure_hash.h>
+#include <gtest/gtest_prod.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+const uint8_t kContinueSession = 1;
+const size_t kAesKeySize = 16; // 128 bits is minimum AES key size.
+const size_t kHashDigestSize = 32; // 256 bits is SHA256 digest size.
+
+// HmacAuthorizationDelegate is an implementation of the AuthorizationDelegate
+// interface. It provides the necessary Auth data for HMAC sessions.
+// This delegate also does parameter encryption on sessions that support it.
+
+// Usage:
+// 1) After running the StartAuthSession command on the TPM2.0, we declare this
+// delegate using the constructor. We can specify if we want parameter
+// obfuscation enabled or not.
+// 2) We initialize the session using |InitSession|. We feed in the handle and
+// tpm_nonce returned by StartAuthSession. Additionally we inject the
+// caller_nonce, salt and auth_value of the bound entity we fed into
+// StartAuthSession.
+// 3) Pass a pointer to this delegate to any TPM command that needs
+// authorization using this delegate.
+
+// Sample control flow:
+// TrunksProxy proxy;
+// proxy.Init();
+// Tpm tpm(&proxy);
+// tpm.StartAuthSession(...);
+// HmacAuthorizationDelegate hmac();
+// hmac.InitSession(...);
+// tpm.Create(..., &hmac);
+// hmac.set_entity_authorization_value(...);
+// tpm.Load(..., &hmac);
+class TRUNKS_EXPORT HmacAuthorizationDelegate: public AuthorizationDelegate {
+ public:
+ HmacAuthorizationDelegate();
+ ~HmacAuthorizationDelegate() override;
+
+ // AuthorizationDelegate methods.
+ bool GetCommandAuthorization(const std::string& command_hash,
+ bool is_command_parameter_encryption_possible,
+ bool is_response_parameter_encryption_possible,
+ std::string* authorization) override;
+ bool CheckResponseAuthorization(const std::string& response_hash,
+ const std::string& authorization) override;
+ bool EncryptCommandParameter(std::string* parameter) override;
+ bool DecryptResponseParameter(std::string* parameter) override;
+
+ // This function is called with the return data of |StartAuthSession|. It
+ // will initialize the session to start providing auth information. It can
+ // only be called once per delegate, and must be called before the delegate
+ // is used for any operation. The boolean arg |enable_parameter_encryption|
+ // specifies if parameter encryption should be enabled for this delegate.
+ // |salt| and |bind_auth_value| specify the injected auth values into this
+ // delegate.
+ bool InitSession(TPM_HANDLE session_handle,
+ const TPM2B_NONCE& tpm_nonce,
+ const TPM2B_NONCE& caller_nonce,
+ const std::string& salt,
+ const std::string& bind_auth_value,
+ bool enable_parameter_encryption);
+
+ // This method sets the FutureAuthorizationValue. This value is used in
+ // computing the HMAC response of TPM2_HierarchyChangeAuth.
+ void set_future_authorization_value(const std::string& auth_value);
+
+ std::string future_authorization_value() {
+ return future_authorization_value_;
+ }
+
+ // This method is used to inject an auth_value associated with an entity.
+ // This auth_value is then used when generating HMACs and encryption keys.
+ // Note: This value will be used for all commands until explicitly reset.
+ void set_entity_authorization_value(const std::string& auth_value) {
+ entity_authorization_value_ = auth_value;
+ }
+
+ std::string entity_authorization_value() const {
+ return entity_authorization_value_;
+ }
+
+ TPM_HANDLE session_handle() const {
+ return session_handle_;
+ }
+
+ void set_use_entity_authorization_for_encryption_only(bool value) {
+ use_entity_authorization_for_encryption_only_ = value;
+ }
+
+ protected:
+ FRIEND_TEST(HmacAuthorizationDelegateFixture, NonceRegenerationTest);
+ FRIEND_TEST(HmacAuthorizationDelegateTest, EncryptDecryptTest);
+ FRIEND_TEST(HmacAuthorizationDelegateTest, SessionKeyTest);
+
+ private:
+ // This method implements the key derivation function used in the TPM.
+ // NOTE: It only returns 32 byte keys.
+ std::string CreateKey(const std::string& hmac_key,
+ const std::string& label,
+ const TPM2B_NONCE& nonce_newer,
+ const TPM2B_NONCE& nonce_older);
+ // This method performs a FIPS198 HMAC operation on |data| using |key|
+ std::string HmacSha256(const std::string& key,
+ const std::string& data);
+ // This method performs an AES operation using a 128 bit key.
+ // |operation_type| can be either AES_ENCRYPT or AES_DECRYPT and it
+ // determines if the operation is an encryption or decryption.
+ void AesOperation(std::string* parameter,
+ const TPM2B_NONCE& nonce_newer,
+ const TPM2B_NONCE& nonce_older,
+ int operation_type);
+ // This method regenerates the caller nonce. The new nonce is the same
+ // length as the previous nonce. The buffer is filled with random data using
+ // openssl's |RAND_bytes| function.
+ // NOTE: This operation is DESTRUCTIVE, and rewrites the caller_nonce_ field.
+ void RegenerateCallerNonce();
+
+ TPM_HANDLE session_handle_;
+ TPM2B_NONCE caller_nonce_;
+ TPM2B_NONCE tpm_nonce_;
+ bool is_parameter_encryption_enabled_;
+ bool nonce_generated_;
+ std::string session_key_;
+ std::string entity_authorization_value_;
+ bool future_authorization_value_set_;
+ std::string future_authorization_value_;
+ // This boolean flag determines if the entity_authorization_value_ is needed
+ // when computing the hmac_key to create the authorization hmac. Defaults
+ // to false, but policy sessions may set this flag to true.
+ bool use_entity_authorization_for_encryption_only_;
+
+ DISALLOW_COPY_AND_ASSIGN(HmacAuthorizationDelegate);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
diff --git a/trunks/hmac_authorization_delegate_test.cc b/trunks/hmac_authorization_delegate_test.cc
new file mode 100644
index 0000000..025c80a
--- /dev/null
+++ b/trunks/hmac_authorization_delegate_test.cc
@@ -0,0 +1,272 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "trunks/hmac_authorization_delegate.h"
+
+namespace trunks {
+
+TEST(HmacAuthorizationDelegateTest, UninitializedSessionTest) {
+ HmacAuthorizationDelegate delegate;
+ std::string dummy;
+ std::string p_hash("test");
+ EXPECT_FALSE(delegate.GetCommandAuthorization(p_hash, false, false, &dummy));
+ EXPECT_EQ(0, dummy.size());
+ EXPECT_FALSE(delegate.CheckResponseAuthorization(p_hash, dummy));
+ EXPECT_FALSE(delegate.EncryptCommandParameter(&dummy));
+ EXPECT_FALSE(delegate.DecryptResponseParameter(&dummy));
+}
+
+TEST(HmacAuthorizationDelegateTest, SessionKeyTest) {
+ HmacAuthorizationDelegate delegate;
+ TPM2B_NONCE nonce;
+ nonce.size = kAesKeySize;
+ memset(nonce.buffer, 0, nonce.size);
+ TPM_HANDLE dummy_handle = HMAC_SESSION_FIRST;
+ EXPECT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, std::string(),
+ std::string(), false));
+ EXPECT_EQ(0, delegate.session_key_.size());
+
+ std::string dummy_auth = std::string("authorization");
+ std::string dummy_salt = std::string("salt");
+ EXPECT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, dummy_salt,
+ dummy_auth, false));
+ EXPECT_EQ(kHashDigestSize, delegate.session_key_.size());
+ // TODO(usanghi): Use TCG TPM2.0 test vectors when available.
+ std::string expected_key("\xfb\x2f\x3c\x33\x65\x3e\xdc\x47"
+ "\xda\xbe\x4e\xb7\xf4\x6c\x19\x4d"
+ "\xea\x50\xb2\x11\x54\x45\x32\x73"
+ "\x47\x38\xef\xb3\x4a\x82\x29\x94",
+ kHashDigestSize);
+ EXPECT_EQ(0, expected_key.compare(delegate.session_key_));
+}
+
+TEST(HmacAuthorizationDelegateTest, EncryptDecryptTest) {
+ HmacAuthorizationDelegate delegate;
+ std::string plaintext_parameter("parameter");
+ std::string encrypted_parameter(plaintext_parameter);
+ // Test with session not initialized.
+ EXPECT_FALSE(delegate.EncryptCommandParameter(&encrypted_parameter));
+ EXPECT_FALSE(delegate.DecryptResponseParameter(&encrypted_parameter));
+ // Test with encryption not enabled.
+ TPM_HANDLE dummy_handle = HMAC_SESSION_FIRST;
+ TPM2B_NONCE nonce;
+ nonce.size = kAesKeySize;
+ std::string salt("salt");
+ ASSERT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, salt,
+ std::string(), false));
+ EXPECT_TRUE(delegate.EncryptCommandParameter(&encrypted_parameter));
+ EXPECT_EQ(0, plaintext_parameter.compare(encrypted_parameter));
+ EXPECT_TRUE(delegate.DecryptResponseParameter(&encrypted_parameter));
+ EXPECT_EQ(0, plaintext_parameter.compare(encrypted_parameter));
+ // Test with encryption enabled.
+ ASSERT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, salt,
+ std::string(), true));
+ EXPECT_TRUE(delegate.EncryptCommandParameter(&encrypted_parameter));
+ EXPECT_NE(0, plaintext_parameter.compare(encrypted_parameter));
+ // Calling EncryptCommandParameter regenerated the caller_nonce.
+ // We need to manually switch tpm_nonce and caller_nonce to ensure
+ // that DecryptResponseParameter has the correct nonces.
+ delegate.tpm_nonce_ = delegate.caller_nonce_;
+ delegate.caller_nonce_ = nonce;
+ EXPECT_TRUE(delegate.DecryptResponseParameter(&encrypted_parameter));
+ EXPECT_EQ(0, plaintext_parameter.compare(encrypted_parameter));
+}
+
+class HmacAuthorizationDelegateFixture : public testing::Test {
+ public:
+ HmacAuthorizationDelegateFixture() {}
+ ~HmacAuthorizationDelegateFixture() override {}
+
+ void SetUp() override {
+ session_handle_ = HMAC_SESSION_FIRST;
+ session_nonce_.size = kAesKeySize;
+ memset(session_nonce_.buffer, 0, kAesKeySize);
+ ASSERT_TRUE(delegate_.InitSession(session_handle_,
+ session_nonce_, // TPM nonce.
+ session_nonce_, // Caller nonce.
+ std::string(), // Salt.
+ std::string(), // Bind auth value.
+ false)); // Enable encryption.
+ }
+
+ protected:
+ TPM_HANDLE session_handle_;
+ TPM2B_NONCE session_nonce_;
+ HmacAuthorizationDelegate delegate_;
+};
+
+TEST_F(HmacAuthorizationDelegateFixture, NonceRegenerationTest) {
+ ASSERT_TRUE(delegate_.InitSession(session_handle_,
+ session_nonce_, // TPM nonce.
+ session_nonce_, // Caller nonce.
+ std::string(), // Salt.
+ std::string(), // Bind auth value.
+ true)); // Enable encryption.
+ TPM2B_NONCE original_nonce = session_nonce_;
+ EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
+ EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer,
+ original_nonce.buffer,
+ original_nonce.size));
+ // First we check that performing GetCommandAuthorization resets the nonce.
+ std::string command_hash;
+ std::string authorization;
+ TPMS_AUTH_COMMAND auth_command;
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(command_hash, false, false,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ nullptr));
+ EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
+ EXPECT_EQ(auth_command.nonce.size, original_nonce.size);
+ EXPECT_NE(0, memcmp(delegate_.caller_nonce_.buffer,
+ original_nonce.buffer,
+ original_nonce.size));
+ EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer,
+ auth_command.nonce.buffer,
+ auth_command.nonce.size));
+ // Now we check that GetCommandAuthorization does not reset nonce
+ // when EncryptCommandParameter is called first.
+ original_nonce = delegate_.caller_nonce_;
+ std::string parameter;
+ EXPECT_TRUE(delegate_.EncryptCommandParameter(&parameter));
+ EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
+ EXPECT_NE(0, memcmp(delegate_.caller_nonce_.buffer,
+ original_nonce.buffer,
+ original_nonce.size));
+ EXPECT_TRUE(delegate_.nonce_generated_);
+ original_nonce = delegate_.caller_nonce_;
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(command_hash, false, false,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ nullptr));
+ EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
+ EXPECT_EQ(auth_command.nonce.size, original_nonce.size);
+ EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer,
+ original_nonce.buffer,
+ original_nonce.size));
+ EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer,
+ auth_command.nonce.buffer,
+ auth_command.nonce.size));
+}
+
+TEST_F(HmacAuthorizationDelegateFixture, CommandAuthTest) {
+ std::string command_hash;
+ std::string authorization;
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(command_hash, false, false,
+ &authorization));
+ TPMS_AUTH_COMMAND auth_command;
+ std::string auth_bytes;
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(auth_command.session_handle, session_handle_);
+ EXPECT_EQ(auth_command.nonce.size, session_nonce_.size);
+ EXPECT_EQ(kContinueSession, auth_command.session_attributes);
+ EXPECT_EQ(kHashDigestSize, auth_command.hmac.size);
+}
+
+TEST_F(HmacAuthorizationDelegateFixture, ResponseAuthTest) {
+ TPMS_AUTH_RESPONSE auth_response;
+ auth_response.session_attributes = kContinueSession;
+ auth_response.nonce.size = kAesKeySize;
+ memset(auth_response.nonce.buffer, 0, kAesKeySize);
+ auth_response.hmac.size = kHashDigestSize;
+ // TODO(usanghi): Use TCG TPM2.0 test vectors when available.
+ uint8_t hmac_buffer[kHashDigestSize] =
+ {0x37, 0x69, 0xaf, 0x12, 0xff, 0x4d, 0xbf, 0x44,
+ 0xe5, 0x16, 0xa2, 0x2d, 0x1d, 0x05, 0x12, 0xe8,
+ 0xbc, 0x42, 0x51, 0x6d, 0x59, 0xe8, 0xbf, 0x40,
+ 0x1e, 0xa3, 0x46, 0xa4, 0xd6, 0x0d, 0xcc, 0xf7};
+ memcpy(auth_response.hmac.buffer, hmac_buffer, kHashDigestSize);
+ std::string response_hash;
+ std::string authorization;
+ EXPECT_EQ(TPM_RC_SUCCESS, Serialize_TPMS_AUTH_RESPONSE(auth_response,
+ &authorization));
+ EXPECT_TRUE(delegate_.CheckResponseAuthorization(response_hash,
+ authorization));
+}
+
+TEST_F(HmacAuthorizationDelegateFixture, SessionAttributes) {
+ const uint8_t kDecryptSession = 1<<5;
+ const uint8_t kEncryptSession = 1<<6;
+
+ // Encryption disabled and not possible for command.
+ std::string authorization;
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), false, false,
+ &authorization));
+ TPMS_AUTH_COMMAND auth_command;
+ std::string auth_bytes;
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(kContinueSession, auth_command.session_attributes);
+
+ // Encryption disabled and possible for command.
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), true, true,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(kContinueSession, auth_command.session_attributes);
+
+ // Encryption enabled and not possible for command.
+ ASSERT_TRUE(delegate_.InitSession(session_handle_,
+ session_nonce_, // TPM nonce.
+ session_nonce_, // Caller nonce.
+ std::string(), // Salt.
+ std::string(), // Bind auth value.
+ true)); // Enable encryption.
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), false, false,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(kContinueSession, auth_command.session_attributes);
+
+ // Encryption enabled and possible only for command input.
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), true, false,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(kContinueSession | kDecryptSession,
+ auth_command.session_attributes);
+
+ // Encryption enabled and possible only for command output.
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), false, true,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(kContinueSession | kEncryptSession,
+ auth_command.session_attributes);
+
+ // Encryption enabled and possible for command input and output.
+ EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), true, true,
+ &authorization));
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(&authorization,
+ &auth_command,
+ &auth_bytes));
+ EXPECT_EQ(kContinueSession | kEncryptSession | kDecryptSession,
+ auth_command.session_attributes);
+}
+
+} // namespace trunks
diff --git a/trunks/hmac_session.h b/trunks/hmac_session.h
new file mode 100644
index 0000000..0b94765
--- /dev/null
+++ b/trunks/hmac_session.h
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_HMAC_SESSION_H_
+#define TRUNKS_HMAC_SESSION_H_
+
+#include <string>
+
+#include <base/macros.h>
+
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+class AuthorizationDelegate;
+
+// HmacSession is an interface for managing hmac backed sessions for
+// authorization and parameter encryption.
+class HmacSession {
+ public:
+ HmacSession() {}
+ virtual ~HmacSession() {}
+
+ // Returns an authorization delegate for this session. Ownership of the
+ // delegate pointer is retained by the session.
+ virtual AuthorizationDelegate* GetDelegate() = 0;
+
+ // Starts a salted session which is bound to |bind_entity| with
+ // |bind_authorization_value|. Encryption is enabled if |enable_encryption| is
+ // true. The session remains active until this object is destroyed or another
+ // session is started with a call to Start*Session.
+ virtual TPM_RC StartBoundSession(
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) = 0;
+
+ // Starts a salted, unbound session. Encryption is enabled if
+ // |enable_encryption| is true. The session remains active until this object
+ // is destroyed or another session is started with a call to Start*Session.
+ virtual TPM_RC StartUnboundSession(bool enable_encryption) = 0;
+
+ // Sets the current entity authorization value. This can be safely called
+ // while the session is active and subsequent commands will use the value.
+ virtual void SetEntityAuthorizationValue(const std::string& value) = 0;
+
+ // Sets the future_authorization_value field in the HmacDelegate. This
+ // is used in response validation for the TPM2_HierarchyChangeAuth command.
+ // We need to perform this because the HMAC value returned from
+ // HierarchyChangeAuth uses the new auth_value.
+ virtual void SetFutureAuthorizationValue(const std::string& value) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HmacSession);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_HMAC_SESSION_H_
diff --git a/trunks/hmac_session_impl.cc b/trunks/hmac_session_impl.cc
new file mode 100644
index 0000000..48e0b2a
--- /dev/null
+++ b/trunks/hmac_session_impl.cc
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/hmac_session_impl.h"
+
+#include <string>
+
+#include <base/logging.h>
+#include <base/macros.h>
+#include <base/stl_util.h>
+#include <openssl/rand.h>
+
+namespace trunks {
+
+HmacSessionImpl::HmacSessionImpl(const TrunksFactory& factory)
+ : factory_(factory) {
+ session_manager_ = factory_.GetSessionManager();
+}
+
+HmacSessionImpl::~HmacSessionImpl() {
+ session_manager_->CloseSession();
+}
+
+AuthorizationDelegate* HmacSessionImpl::GetDelegate() {
+ if (session_manager_->GetSessionHandle() == kUninitializedHandle) {
+ return nullptr;
+ }
+ return &hmac_delegate_;
+}
+
+TPM_RC HmacSessionImpl::StartBoundSession(
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) {
+ return session_manager_->StartSession(TPM_SE_HMAC, bind_entity,
+ bind_authorization_value,
+ enable_encryption, &hmac_delegate_);
+}
+
+TPM_RC HmacSessionImpl::StartUnboundSession(bool enable_encryption) {
+ // Starting an unbound session is the same as starting a session bound to
+ // TPM_RH_NULL. In this case, the authorization is the zero length buffer.
+ // We can therefore simply call StartBoundSession with TPM_RH_NULL as the
+ // binding entity, and the empty string as the authorization.
+ return StartBoundSession(TPM_RH_NULL, "", enable_encryption);
+}
+
+void HmacSessionImpl::SetEntityAuthorizationValue(
+ const std::string& value) {
+ hmac_delegate_.set_entity_authorization_value(value);
+}
+
+void HmacSessionImpl::SetFutureAuthorizationValue(
+ const std::string& value) {
+ hmac_delegate_.set_future_authorization_value(value);
+}
+
+} // namespace trunks
diff --git a/trunks/hmac_session_impl.h b/trunks/hmac_session_impl.h
new file mode 100644
index 0000000..a2d9eb9
--- /dev/null
+++ b/trunks/hmac_session_impl.h
@@ -0,0 +1,81 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_HMAC_SESSION_IMPL_H_
+#define TRUNKS_HMAC_SESSION_IMPL_H_
+
+#include "trunks/hmac_session.h"
+
+#include <string>
+
+#include <base/macros.h>
+
+#include "trunks/hmac_authorization_delegate.h"
+#include "trunks/session_manager.h"
+#include "trunks/trunks_export.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+
+// This class implements the HmacSession interface. It is used for
+// keeping track of the HmacAuthorizationDelegate used for commands, and to
+// provide authorization for commands that need it. It is instantiated by
+// TpmUtilityImpl. If we need to use this class outside of TpmUtility, we
+// can use it as below:
+// TrunksFactoryImpl factory;
+// HmacSessionImpl session(factory);
+// session.StartBoundSession(bind_entity, bind_authorization, true);
+// session.SetEntityAuthorizationValue(entity_authorization);
+// factory.GetTpm()->RSA_EncrpytSync(_,_,_,_, session.GetDelegate());
+// NOTE: StartBoundSession/StartUnboundSession should not be called before
+// TPM Ownership is taken. This is because starting a session uses the
+// SaltingKey, which is only created after ownership is taken.
+class TRUNKS_EXPORT HmacSessionImpl: public HmacSession {
+ public:
+ // The constructor for HmacAuthroizationSession needs a factory. In
+ // producation code, this factory is used to access the TPM class to forward
+ // commands to the TPM. In test code, this is used to mock out the TPM calls.
+ explicit HmacSessionImpl(const TrunksFactory& factory);
+ ~HmacSessionImpl() override;
+
+ // HmacSession methods.
+ AuthorizationDelegate* GetDelegate() override;
+ TPM_RC StartBoundSession(TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) override;
+ TPM_RC StartUnboundSession(bool enable_encryption) override;
+ void SetEntityAuthorizationValue(const std::string& value) override;
+ void SetFutureAuthorizationValue(const std::string& value) override;
+
+ private:
+ // This factory is only set in the constructor and is used to instantiate
+ // The TPM class to forward commands to the TPM chip.
+ const TrunksFactory& factory_;
+ // This delegate is what provides authorization to commands. It is what is
+ // returned when the GetDelegate method is called.
+ HmacAuthorizationDelegate hmac_delegate_;
+ // This object is used to manage the TPM session associated with this
+ // HmacSession.
+ scoped_ptr<SessionManager> session_manager_;
+
+ friend class HmacSessionTest;
+ DISALLOW_COPY_AND_ASSIGN(HmacSessionImpl);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_HMAC_SESSION_IMPL_H_
diff --git a/trunks/hmac_session_test.cc b/trunks/hmac_session_test.cc
new file mode 100644
index 0000000..8df82c1
--- /dev/null
+++ b/trunks/hmac_session_test.cc
@@ -0,0 +1,105 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/hmac_session_impl.h"
+
+#include <base/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/mock_session_manager.h"
+#include "trunks/mock_tpm.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::NiceMock;
+using testing::Return;
+using testing::SaveArg;
+using testing::SetArgPointee;
+
+namespace trunks {
+
+class HmacSessionTest : public testing::Test {
+ public:
+ HmacSessionTest() {}
+ ~HmacSessionTest() override {}
+
+ void SetUp() override {
+ factory_.set_tpm(&mock_tpm_);
+ factory_.set_session_manager(&mock_session_manager_);
+ }
+
+ HmacAuthorizationDelegate* GetHmacDelegate(HmacSessionImpl* session) {
+ return &(session->hmac_delegate_);
+ }
+
+ protected:
+ TrunksFactoryForTest factory_;
+ NiceMock<MockTpm> mock_tpm_;
+ NiceMock<MockSessionManager> mock_session_manager_;
+};
+
+TEST_F(HmacSessionTest, GetDelegateUninitialized) {
+ HmacSessionImpl session(factory_);
+ EXPECT_CALL(mock_session_manager_, GetSessionHandle())
+ .WillRepeatedly(Return(kUninitializedHandle));
+ EXPECT_EQ(nullptr, session.GetDelegate());
+}
+
+TEST_F(HmacSessionTest, GetDelegateSuccess) {
+ HmacSessionImpl session(factory_);
+ EXPECT_EQ(GetHmacDelegate(&session), session.GetDelegate());
+}
+
+TEST_F(HmacSessionTest, StartBoundSessionSuccess) {
+ HmacSessionImpl session(factory_);
+ TPM_HANDLE bind_entity = TPM_RH_FIRST;
+ EXPECT_CALL(mock_session_manager_, StartSession(TPM_SE_HMAC, bind_entity,
+ _, true, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, session.StartBoundSession(bind_entity, "", true));
+}
+
+TEST_F(HmacSessionTest, StartBoundSessionFailure) {
+ HmacSessionImpl session(factory_);
+ TPM_HANDLE bind_entity = TPM_RH_FIRST;
+ EXPECT_CALL(mock_session_manager_, StartSession(TPM_SE_HMAC, bind_entity,
+ _, true, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.StartBoundSession(bind_entity, "", true));
+}
+
+TEST_F(HmacSessionTest, EntityAuthorizationForwardingTest) {
+ HmacSessionImpl session(factory_);
+ std::string test_auth("test_auth");
+ session.SetEntityAuthorizationValue(test_auth);
+ HmacAuthorizationDelegate* hmac_delegate = GetHmacDelegate(&session);
+ std::string entity_auth = hmac_delegate->entity_authorization_value();
+ EXPECT_EQ(0, test_auth.compare(entity_auth));
+}
+
+TEST_F(HmacSessionTest, FutureAuthorizationForwardingTest) {
+ HmacSessionImpl session(factory_);
+ std::string test_auth("test_auth");
+ session.SetFutureAuthorizationValue(test_auth);
+ HmacAuthorizationDelegate* hmac_delegate = GetHmacDelegate(&session);
+ std::string entity_auth = hmac_delegate->future_authorization_value();
+ EXPECT_EQ(0, test_auth.compare(entity_auth));
+}
+
+} // namespace trunks
diff --git a/trunks/mock_authorization_delegate.cc b/trunks/mock_authorization_delegate.cc
new file mode 100644
index 0000000..ed618ab
--- /dev/null
+++ b/trunks/mock_authorization_delegate.cc
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_authorization_delegate.h"
+
+namespace trunks {
+
+MockAuthorizationDelegate::MockAuthorizationDelegate() {}
+MockAuthorizationDelegate::~MockAuthorizationDelegate() {}
+
+} // namespace trunks
diff --git a/trunks/mock_authorization_delegate.h b/trunks/mock_authorization_delegate.h
new file mode 100644
index 0000000..72b63d3
--- /dev/null
+++ b/trunks/mock_authorization_delegate.h
@@ -0,0 +1,49 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_AUTHORIZATION_DELEGATE_H_
+#define TRUNKS_MOCK_AUTHORIZATION_DELEGATE_H_
+
+#include <string>
+
+#include <base/basictypes.h>
+#include <gmock/gmock.h>
+
+#include "trunks/authorization_delegate.h"
+
+namespace trunks {
+
+class MockAuthorizationDelegate : public AuthorizationDelegate {
+ public:
+ MockAuthorizationDelegate();
+ ~MockAuthorizationDelegate() override;
+
+ MOCK_METHOD4(GetCommandAuthorization, bool(const std::string&,
+ bool,
+ bool,
+ std::string*));
+ MOCK_METHOD2(CheckResponseAuthorization, bool(const std::string&,
+ const std::string&));
+ MOCK_METHOD1(EncryptCommandParameter, bool(std::string*));
+ MOCK_METHOD1(DecryptResponseParameter, bool(std::string*));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockAuthorizationDelegate);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_AUTHORIZATION_DELEGATE_H_
diff --git a/trunks/mock_blob_parser.cc b/trunks/mock_blob_parser.cc
new file mode 100644
index 0000000..082704f
--- /dev/null
+++ b/trunks/mock_blob_parser.cc
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_blob_parser.h"
+
+#include <gmock/gmock.h>
+
+using testing::_;
+using testing::Return;
+
+namespace trunks {
+
+MockBlobParser::MockBlobParser() {
+ ON_CALL(*this, SerializeKeyBlob(_, _, _)).WillByDefault(Return(true));
+ ON_CALL(*this, ParseKeyBlob(_, _, _)).WillByDefault(Return(true));
+ ON_CALL(*this, SerializeCreationBlob(_, _, _, _)).WillByDefault(Return(true));
+ ON_CALL(*this, ParseCreationBlob(_, _, _, _)).WillByDefault(Return(true));
+}
+
+MockBlobParser::~MockBlobParser() {}
+
+} // namespace trunks
diff --git a/trunks/mock_blob_parser.h b/trunks/mock_blob_parser.h
new file mode 100644
index 0000000..f6f3d6e
--- /dev/null
+++ b/trunks/mock_blob_parser.h
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_BLOB_PARSER_H_
+#define TRUNKS_MOCK_BLOB_PARSER_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "trunks/blob_parser.h"
+
+namespace trunks {
+
+class MockBlobParser : public BlobParser {
+ public:
+ MockBlobParser();
+ ~MockBlobParser() override;
+
+ MOCK_METHOD3(SerializeKeyBlob, bool(const TPM2B_PUBLIC&,
+ const TPM2B_PRIVATE&,
+ std::string*));
+ MOCK_METHOD3(ParseKeyBlob, bool(const std::string&,
+ TPM2B_PUBLIC*,
+ TPM2B_PRIVATE*));
+ MOCK_METHOD4(SerializeCreationBlob, bool(const TPM2B_CREATION_DATA&,
+ const TPM2B_DIGEST&,
+ const TPMT_TK_CREATION&,
+ std::string*));
+ MOCK_METHOD4(ParseCreationBlob, bool(const std::string&,
+ TPM2B_CREATION_DATA*,
+ TPM2B_DIGEST*,
+ TPMT_TK_CREATION*));
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_BLOB_PARSER_H_
diff --git a/trunks/mock_command_transceiver.cc b/trunks/mock_command_transceiver.cc
new file mode 100644
index 0000000..5168fb0
--- /dev/null
+++ b/trunks/mock_command_transceiver.cc
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_command_transceiver.h"
+
+namespace trunks {
+
+MockCommandTransceiver::MockCommandTransceiver() {}
+MockCommandTransceiver::~MockCommandTransceiver() {}
+
+} // namespace trunks
diff --git a/trunks/mock_command_transceiver.h b/trunks/mock_command_transceiver.h
new file mode 100644
index 0000000..9c94f2b
--- /dev/null
+++ b/trunks/mock_command_transceiver.h
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_COMMAND_TRANSCEIVER_H_
+#define TRUNKS_MOCK_COMMAND_TRANSCEIVER_H_
+
+#include <string>
+
+#include <base/basictypes.h>
+#include <base/callback.h>
+#include <gmock/gmock.h>
+
+#include "trunks/command_transceiver.h"
+
+namespace trunks {
+
+class MockCommandTransceiver : public CommandTransceiver {
+ public:
+ MockCommandTransceiver();
+ ~MockCommandTransceiver() override;
+
+ MOCK_METHOD2(SendCommand, void(const std::string&, const ResponseCallback&));
+ MOCK_METHOD1(SendCommandAndWait, std::string(const std::string&));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockCommandTransceiver);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_COMMAND_TRANSCEIVER_H_
diff --git a/trunks/mock_hmac_session.cc b/trunks/mock_hmac_session.cc
new file mode 100644
index 0000000..8ccb4d9
--- /dev/null
+++ b/trunks/mock_hmac_session.cc
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_hmac_session.h"
+
+namespace trunks {
+
+MockHmacSession::MockHmacSession() {}
+MockHmacSession::~MockHmacSession() {}
+
+} // namespace trunks
diff --git a/trunks/mock_hmac_session.h b/trunks/mock_hmac_session.h
new file mode 100644
index 0000000..3bd1fad
--- /dev/null
+++ b/trunks/mock_hmac_session.h
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_HMAC_SESSION_H_
+#define TRUNKS_MOCK_HMAC_SESSION_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "trunks/hmac_session.h"
+
+namespace trunks {
+
+class MockHmacSession : public HmacSession {
+ public:
+ MockHmacSession();
+ ~MockHmacSession() override;
+
+ MOCK_METHOD0(GetDelegate, AuthorizationDelegate*());
+ MOCK_METHOD3(StartBoundSession, TPM_RC(
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption));
+ MOCK_METHOD1(StartUnboundSession, TPM_RC(bool enable_encryption));
+ MOCK_METHOD1(SetEntityAuthorizationValue, void(const std::string& value));
+ MOCK_METHOD1(SetFutureAuthorizationValue, void(const std::string& value));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockHmacSession);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_HMAC_SESSION_H_
diff --git a/trunks/mock_policy_session.cc b/trunks/mock_policy_session.cc
new file mode 100644
index 0000000..6a61198
--- /dev/null
+++ b/trunks/mock_policy_session.cc
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_policy_session.h"
+
+namespace trunks {
+
+MockPolicySession::MockPolicySession() {}
+MockPolicySession::~MockPolicySession() {}
+
+} // namespace trunks
diff --git a/trunks/mock_policy_session.h b/trunks/mock_policy_session.h
new file mode 100644
index 0000000..2ce4214
--- /dev/null
+++ b/trunks/mock_policy_session.h
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_POLICY_SESSION_H_
+#define TRUNKS_MOCK_POLICY_SESSION_H_
+
+#include <string>
+#include <vector>
+
+#include <gmock/gmock.h>
+
+#include "trunks/policy_session.h"
+
+namespace trunks {
+
+class MockPolicySession : public PolicySession {
+ public:
+ MockPolicySession();
+ ~MockPolicySession() override;
+
+ MOCK_METHOD0(GetDelegate, AuthorizationDelegate*());
+ MOCK_METHOD3(StartBoundSession, TPM_RC(
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption));
+ MOCK_METHOD1(StartUnboundSession, TPM_RC(bool enable_encryption));
+ MOCK_METHOD1(GetDigest, TPM_RC(std::string*));
+ MOCK_METHOD1(PolicyOR, TPM_RC(const std::vector<std::string>&));
+ MOCK_METHOD2(PolicyPCR, TPM_RC(uint32_t, const std::string&));
+ MOCK_METHOD1(PolicyCommandCode, TPM_RC(TPM_CC));
+ MOCK_METHOD0(PolicyAuthValue, TPM_RC());
+ MOCK_METHOD1(SetEntityAuthorizationValue, void(const std::string&));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockPolicySession);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_POLICY_SESSION_H_
diff --git a/trunks/mock_session_manager.cc b/trunks/mock_session_manager.cc
new file mode 100644
index 0000000..daf480c
--- /dev/null
+++ b/trunks/mock_session_manager.cc
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_session_manager.h"
+
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+MockSessionManager::MockSessionManager() {
+ ON_CALL(*this, GetSessionHandle())
+ .WillByDefault(testing::Return(TPM_RH_FIRST));
+}
+
+MockSessionManager::~MockSessionManager() {}
+
+} // namespace trunks
diff --git a/trunks/mock_session_manager.h b/trunks/mock_session_manager.h
new file mode 100644
index 0000000..e674f0b
--- /dev/null
+++ b/trunks/mock_session_manager.h
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_SESSION_MANAGER_H_
+#define TRUNKS_MOCK_SESSION_MANAGER_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "trunks/session_manager.h"
+
+namespace trunks {
+
+class MockSessionManager : public SessionManager {
+ public:
+ MockSessionManager();
+ ~MockSessionManager() override;
+
+ MOCK_CONST_METHOD0(GetSessionHandle, TPM_HANDLE());
+ MOCK_METHOD0(CloseSession, void());
+ MOCK_METHOD5(StartSession, TPM_RC(TPM_SE,
+ TPMI_DH_ENTITY,
+ const std::string&,
+ bool,
+ HmacAuthorizationDelegate*));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSessionManager);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_SESSION_MANAGER_H_
diff --git a/trunks/mock_tpm.cc b/trunks/mock_tpm.cc
new file mode 100644
index 0000000..41ebd2a
--- /dev/null
+++ b/trunks/mock_tpm.cc
@@ -0,0 +1,255 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_tpm.h"
+
+#include "trunks/tpm_utility.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgPointee;
+
+namespace trunks {
+
+MockTpm::MockTpm() : Tpm(nullptr) {
+ ON_CALL(*this, PCR_AllocateSync(_, _, _, _, _, _, _, _))
+ .WillByDefault(DoAll(SetArgPointee<3>(YES),
+ Return(TPM_RC_SUCCESS)));
+}
+
+MockTpm::~MockTpm() {}
+
+void MockTpm::StartAuthSession(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const StartAuthSessionResponse& callback) {
+ StartAuthSessionShort(tpm_key, bind, nonce_caller, encrypted_salt,
+ session_type, symmetric, auth_hash,
+ authorization_delegate, callback);
+}
+
+TPM_RC MockTpm::StartAuthSessionSync(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate) {
+ return StartAuthSessionSyncShort(tpm_key, bind, nonce_caller,
+ encrypted_salt, session_type, symmetric,
+ auth_hash, session_handle, nonce_tpm,
+ authorization_delegate);
+}
+TPM_RC MockTpm::CreateSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ return CreateSyncShort(parent_handle, in_sensitive, in_public, creation_pcr,
+ out_private, out_public, creation_data,
+ creation_hash, creation_ticket,
+ authorization_delegate);
+}
+TPM_RC MockTpm::CertifyCreationSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ return CertifyCreationSyncShort(sign_handle, object_handle,
+ qualifying_data, creation_hash, in_scheme,
+ creation_ticket, certify_info, signature,
+ authorization_delegate);
+}
+TPM_RC MockTpm::GetSessionAuditDigestSync(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ return GetSessionAuditDigestSyncShort(privacy_admin_handle, sign_handle,
+ session_handle, qualifying_data,
+ in_scheme, audit_info, signature,
+ authorization_delegate);
+}
+TPM_RC MockTpm::CommitSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate) {
+ return CommitSyncShort(sign_handle, param_size, p1, y2, param_size_out, k,
+ l, e, counter, authorization_delegate);
+}
+void MockTpm::PolicySigned(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySignedResponse& callback) {
+ PolicySignedShort(auth_object, policy_session, nonce_tpm, cp_hash_a,
+ policy_ref, expiration, auth, authorization_delegate,
+ callback);
+}
+TPM_RC MockTpm::PolicySignedSync(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ return PolicySignedSyncShort(auth_object, policy_session, nonce_tpm,
+ cp_hash_a, policy_ref, expiration, auth, timeout,
+ policy_ticket, authorization_delegate);
+}
+TPM_RC MockTpm::PolicySecretSync(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ return PolicySecretSyncShort(auth_handle, policy_session, nonce_tpm,
+ cp_hash_a, policy_ref, expiration, timeout,
+ policy_ticket, authorization_delegate);
+}
+void MockTpm::PolicyNV(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNVResponse& callback) {
+ PolicyNVShort(auth_handle, nv_index, policy_session, operand_b, offset,
+ operation, authorization_delegate, callback);
+}
+TPM_RC MockTpm::CreatePrimarySync(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ return CreatePrimarySyncShort(primary_handle, in_public, creation_pcr,
+ object_handle, out_public, creation_data,
+ creation_hash, creation_ticket, name,
+ authorization_delegate);
+}
+void MockTpm::NV_Certify(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_CertifyResponse& callback) {
+ NV_CertifyShort(sign_handle, auth_handle, nv_index, qualifying_data,
+ in_scheme, size, offset, authorization_delegate, callback);
+}
+TPM_RC MockTpm::NV_CertifySync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ return NV_CertifySyncShort(sign_handle, auth_handle, nv_index,
+ qualifying_data, in_scheme, size, offset,
+ certify_info, signature, authorization_delegate);
+}
+
+} // namespace trunks
diff --git a/trunks/mock_tpm.h b/trunks/mock_tpm.h
new file mode 100644
index 0000000..7dae456
--- /dev/null
+++ b/trunks/mock_tpm.h
@@ -0,0 +1,1647 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_TPM_H_
+#define TRUNKS_MOCK_TPM_H_
+
+#include <string>
+
+#include <base/callback.h>
+#include <gmock/gmock.h>
+
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+class MockTpm : public Tpm {
+ public:
+ MockTpm();
+ ~MockTpm() override;
+
+ MOCK_METHOD3(Startup,
+ void(const TPM_SU& startup_type,
+ AuthorizationDelegate* authorization_delegate,
+ const StartupResponse& callback));
+ MOCK_METHOD2(StartupSync,
+ TPM_RC(const TPM_SU& startup_type,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(Shutdown,
+ void(const TPM_SU& shutdown_type,
+ AuthorizationDelegate* authorization_delegate,
+ const ShutdownResponse& callback));
+ MOCK_METHOD2(ShutdownSync,
+ TPM_RC(const TPM_SU& shutdown_type,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(SelfTest,
+ void(const TPMI_YES_NO& full_test,
+ AuthorizationDelegate* authorization_delegate,
+ const SelfTestResponse& callback));
+ MOCK_METHOD2(SelfTestSync,
+ TPM_RC(const TPMI_YES_NO& full_test,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(IncrementalSelfTest,
+ void(const TPML_ALG& to_test,
+ AuthorizationDelegate* authorization_delegate,
+ const IncrementalSelfTestResponse& callback));
+ MOCK_METHOD3(IncrementalSelfTestSync,
+ TPM_RC(const TPML_ALG& to_test,
+ TPML_ALG* to_do_list,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD2(GetTestResult,
+ void(AuthorizationDelegate* authorization_delegate,
+ const GetTestResultResponse& callback));
+ MOCK_METHOD3(GetTestResultSync,
+ TPM_RC(TPM2B_MAX_BUFFER* out_data,
+ TPM_RC* test_result,
+ AuthorizationDelegate* authorization_delegate));
+ // Too many args to mock, forward to *Short version.
+ void StartAuthSession(const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const StartAuthSessionResponse& callback) override;
+ MOCK_METHOD9(StartAuthSessionShort,
+ void(const TPMI_DH_OBJECT& tpm_key,
+ const TPMI_DH_ENTITY& bind,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const StartAuthSessionResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC StartAuthSessionSync(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD10(StartAuthSessionSyncShort,
+ TPM_RC(const TPMI_DH_OBJECT& tpm_key,
+ const TPMI_DH_ENTITY& bind,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(PolicyRestart,
+ void(const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyRestartResponse& callback));
+ MOCK_METHOD3(PolicyRestartSync,
+ TPM_RC(const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(Create,
+ void(const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ AuthorizationDelegate* authorization_delegate,
+ const CreateResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC CreateSync(const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD10(CreateSyncShort,
+ TPM_RC(const TPMI_DH_OBJECT& parent_handle,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(Load,
+ void(const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ AuthorizationDelegate* authorization_delegate,
+ const LoadResponse& callback));
+ MOCK_METHOD7(LoadSync,
+ TPM_RC(const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(LoadExternal,
+ void(const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const LoadExternalResponse& callback));
+ MOCK_METHOD6(LoadExternalSync,
+ TPM_RC(const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(ReadPublic,
+ void(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ReadPublicResponse& callback));
+ MOCK_METHOD6(ReadPublicSync,
+ TPM_RC(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_NAME* name,
+ TPM2B_NAME* qualified_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(ActivateCredential,
+ void(const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ AuthorizationDelegate* authorization_delegate,
+ const ActivateCredentialResponse& callback));
+ MOCK_METHOD8(ActivateCredentialSync,
+ TPM_RC(const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ TPM2B_DIGEST* cert_info,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(MakeCredential,
+ void(const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ AuthorizationDelegate* authorization_delegate,
+ const MakeCredentialResponse& callback));
+ MOCK_METHOD7(MakeCredentialSync,
+ TPM_RC(const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ TPM2B_ID_OBJECT* credential_blob,
+ TPM2B_ENCRYPTED_SECRET* secret,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(Unseal,
+ void(const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const UnsealResponse& callback));
+ MOCK_METHOD4(UnsealSync,
+ TPM_RC(const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ TPM2B_SENSITIVE_DATA* out_data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(ObjectChangeAuth,
+ void(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const ObjectChangeAuthResponse& callback));
+ MOCK_METHOD7(ObjectChangeAuthSync,
+ TPM_RC(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(Duplicate,
+ void(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const DuplicateResponse& callback));
+ MOCK_METHOD10(DuplicateSync,
+ TPM_RC(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ TPM2B_DATA* encryption_key_out,
+ TPM2B_PRIVATE* duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD9(Rewrap,
+ void(const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ AuthorizationDelegate* authorization_delegate,
+ const RewrapResponse& callback));
+ MOCK_METHOD10(RewrapSync,
+ TPM_RC(const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ TPM2B_PRIVATE* out_duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD9(Import,
+ void(const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const ImportResponse& callback));
+ MOCK_METHOD9(ImportSync,
+ TPM_RC(const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(RSA_Encrypt,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ AuthorizationDelegate* authorization_delegate,
+ const RSA_EncryptResponse& callback));
+ MOCK_METHOD7(RSA_EncryptSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ TPM2B_PUBLIC_KEY_RSA* out_data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(RSA_Decrypt,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ AuthorizationDelegate* authorization_delegate,
+ const RSA_DecryptResponse& callback));
+ MOCK_METHOD7(RSA_DecryptSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ TPM2B_PUBLIC_KEY_RSA* message,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(ECDH_KeyGen,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ECDH_KeyGenResponse& callback));
+ MOCK_METHOD5(ECDH_KeyGenSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ TPM2B_ECC_POINT* z_point,
+ TPM2B_ECC_POINT* pub_point,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(ECDH_ZGen,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ AuthorizationDelegate* authorization_delegate,
+ const ECDH_ZGenResponse& callback));
+ MOCK_METHOD5(ECDH_ZGenSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ TPM2B_ECC_POINT* out_point,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(ECC_Parameters,
+ void(const TPMI_ECC_CURVE& curve_id,
+ AuthorizationDelegate* authorization_delegate,
+ const ECC_ParametersResponse& callback));
+ MOCK_METHOD3(ECC_ParametersSync,
+ TPM_RC(const TPMI_ECC_CURVE& curve_id,
+ TPMS_ALGORITHM_DETAIL_ECC* parameters,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(ZGen_2Phase,
+ void(const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ AuthorizationDelegate* authorization_delegate,
+ const ZGen_2PhaseResponse& callback));
+ MOCK_METHOD9(ZGen_2PhaseSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ TPM2B_ECC_POINT* out_z1,
+ TPM2B_ECC_POINT* out_z2,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(EncryptDecrypt,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ AuthorizationDelegate* authorization_delegate,
+ const EncryptDecryptResponse& callback));
+ MOCK_METHOD9(EncryptDecryptSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM2B_IV* iv_out,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(Hash,
+ void(const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const HashResponse& callback));
+ MOCK_METHOD6(HashSync,
+ TPM_RC(const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM2B_DIGEST* out_hash,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(HMAC,
+ void(const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HMACResponse& callback));
+ MOCK_METHOD6(HMACSync,
+ TPM_RC(const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ TPM2B_DIGEST* out_hmac,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(GetRandom,
+ void(const UINT16& bytes_requested,
+ AuthorizationDelegate* authorization_delegate,
+ const GetRandomResponse& callback));
+ MOCK_METHOD3(GetRandomSync,
+ TPM_RC(const UINT16& bytes_requested,
+ TPM2B_DIGEST* random_bytes,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(StirRandom,
+ void(const TPM2B_SENSITIVE_DATA& in_data,
+ AuthorizationDelegate* authorization_delegate,
+ const StirRandomResponse& callback));
+ MOCK_METHOD2(StirRandomSync,
+ TPM_RC(const TPM2B_SENSITIVE_DATA& in_data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(HMAC_Start,
+ void(const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HMAC_StartResponse& callback));
+ MOCK_METHOD6(HMAC_StartSync,
+ TPM_RC(const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(HashSequenceStart,
+ void(const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HashSequenceStartResponse& callback));
+ MOCK_METHOD4(HashSequenceStartSync,
+ TPM_RC(const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(SequenceUpdate,
+ void(const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate,
+ const SequenceUpdateResponse& callback));
+ MOCK_METHOD4(SequenceUpdateSync,
+ TPM_RC(const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(SequenceComplete,
+ void(const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const SequenceCompleteResponse& callback));
+ MOCK_METHOD7(SequenceCompleteSync,
+ TPM_RC(const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM2B_DIGEST* result,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(EventSequenceComplete,
+ void(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate,
+ const EventSequenceCompleteResponse& callback));
+ MOCK_METHOD7(EventSequenceCompleteSync,
+ TPM_RC(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ TPML_DIGEST_VALUES* results,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(Certify,
+ void(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const CertifyResponse& callback));
+ MOCK_METHOD9(CertifySync,
+ TPM_RC(const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD10(CertifyCreation,
+ void(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const CertifyCreationResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC CertifyCreationSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD9(CertifyCreationSyncShort,
+ TPM_RC(const TPMI_DH_OBJECT& sign_handle,
+ const TPMI_DH_OBJECT& object_handle,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(Quote,
+ void(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ AuthorizationDelegate* authorization_delegate,
+ const QuoteResponse& callback));
+ MOCK_METHOD8(QuoteSync,
+ TPM_RC(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ TPM2B_ATTEST* quoted,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD10(GetSessionAuditDigest,
+ void(const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetSessionAuditDigestResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC GetSessionAuditDigestSync(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD8(GetSessionAuditDigestSyncShort,
+ TPM_RC(const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const TPMI_DH_OBJECT& sign_handle,
+ const TPMI_SH_HMAC& session_handle,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(GetCommandAuditDigest,
+ void(const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetCommandAuditDigestResponse& callback));
+ MOCK_METHOD9(GetCommandAuditDigestSync,
+ TPM_RC(const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(GetTime,
+ void(const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetTimeResponse& callback));
+ MOCK_METHOD9(GetTimeSync,
+ TPM_RC(const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* time_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(Commit,
+ void(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ AuthorizationDelegate* authorization_delegate,
+ const CommitResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC CommitSync(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD10(CommitSyncShort,
+ TPM_RC(const TPMI_DH_OBJECT& sign_handle,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_ECC_PARAMETER& y2,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(EC_Ephemeral,
+ void(const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ AuthorizationDelegate* authorization_delegate,
+ const EC_EphemeralResponse& callback));
+ MOCK_METHOD6(EC_EphemeralSync,
+ TPM_RC(const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* q,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(VerifySignature,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ AuthorizationDelegate* authorization_delegate,
+ const VerifySignatureResponse& callback));
+ MOCK_METHOD6(VerifySignatureSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ TPMT_TK_VERIFIED* validation,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(Sign,
+ void(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ AuthorizationDelegate* authorization_delegate,
+ const SignResponse& callback));
+ MOCK_METHOD7(SignSync,
+ TPM_RC(const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(SetCommandCodeAuditStatus,
+ void(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate,
+ const SetCommandCodeAuditStatusResponse& callback));
+ MOCK_METHOD6(SetCommandCodeAuditStatusSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PCR_Extend,
+ void(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ExtendResponse& callback));
+ MOCK_METHOD4(PCR_ExtendSync,
+ TPM_RC(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PCR_Event,
+ void(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_EventResponse& callback));
+ MOCK_METHOD5(PCR_EventSync,
+ TPM_RC(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ TPML_DIGEST_VALUES* digests,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(PCR_Read,
+ void(const TPML_PCR_SELECTION& pcr_selection_in,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ReadResponse& callback));
+ MOCK_METHOD5(PCR_ReadSync,
+ TPM_RC(const TPML_PCR_SELECTION& pcr_selection_in,
+ UINT32* pcr_update_counter,
+ TPML_PCR_SELECTION* pcr_selection_out,
+ TPML_DIGEST* pcr_values,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PCR_Allocate,
+ void(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_AllocateResponse& callback));
+ MOCK_METHOD8(PCR_AllocateSync,
+ TPM_RC(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ TPMI_YES_NO* allocation_success,
+ UINT32* max_pcr,
+ UINT32* size_needed,
+ UINT32* size_available,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(PCR_SetAuthPolicy,
+ void(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_SetAuthPolicyResponse& callback));
+ MOCK_METHOD7(PCR_SetAuthPolicySync,
+ TPM_RC(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PCR_SetAuthValue,
+ void(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_SetAuthValueResponse& callback));
+ MOCK_METHOD4(PCR_SetAuthValueSync,
+ TPM_RC(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(PCR_Reset,
+ void(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ResetResponse& callback));
+ MOCK_METHOD3(PCR_ResetSync,
+ TPM_RC(const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ // Too many args to mock, forward to *Short version.
+ void PolicySigned(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySignedResponse& callback) override;
+ MOCK_METHOD9(PolicySignedShort,
+ void(const TPMI_DH_OBJECT& auth_object,
+ const TPMI_SH_POLICY& policy_session,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySignedResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC PolicySignedSync(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD10(PolicySignedSyncShort,
+ TPM_RC(const TPMI_DH_OBJECT& auth_object,
+ const TPMI_SH_POLICY& policy_session,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD10(PolicySecret,
+ void(const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySecretResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC PolicySecretSync(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD9(PolicySecretSyncShort,
+ TPM_RC(const TPMI_DH_ENTITY& auth_handle,
+ const TPMI_SH_POLICY& policy_session,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD9(PolicyTicket,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyTicketResponse& callback));
+ MOCK_METHOD8(PolicyTicketSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PolicyOR,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyORResponse& callback));
+ MOCK_METHOD4(PolicyORSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(PolicyPCR,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPCRResponse& callback));
+ MOCK_METHOD5(PolicyPCRSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PolicyLocality,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyLocalityResponse& callback));
+ MOCK_METHOD4(PolicyLocalitySync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ AuthorizationDelegate* authorization_delegate));
+ // Too many args to mock, forward to *Short version.
+ void PolicyNV(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNVResponse& callback) override;
+ MOCK_METHOD8(PolicyNVShort,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const TPMI_SH_POLICY& policy_session,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNVResponse& callback));
+ MOCK_METHOD10(PolicyNVSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(PolicyCounterTimer,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCounterTimerResponse& callback));
+ MOCK_METHOD6(PolicyCounterTimerSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PolicyCommandCode,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCommandCodeResponse& callback));
+ MOCK_METHOD4(PolicyCommandCodeSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(PolicyPhysicalPresence,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPhysicalPresenceResponse& callback));
+ MOCK_METHOD3(PolicyPhysicalPresenceSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PolicyCpHash,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCpHashResponse& callback));
+ MOCK_METHOD4(PolicyCpHashSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PolicyNameHash,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNameHashResponse& callback));
+ MOCK_METHOD4(PolicyNameHashSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(PolicyDuplicationSelect,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyDuplicationSelectResponse& callback));
+ MOCK_METHOD6(PolicyDuplicationSelectSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(PolicyAuthorize,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyAuthorizeResponse& callback));
+ MOCK_METHOD7(PolicyAuthorizeSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(PolicyAuthValue,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyAuthValueResponse& callback));
+ MOCK_METHOD3(PolicyAuthValueSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(PolicyPassword,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPasswordResponse& callback));
+ MOCK_METHOD3(PolicyPasswordSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(PolicyGetDigest,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyGetDigestResponse& callback));
+ MOCK_METHOD4(PolicyGetDigestSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ TPM2B_DIGEST* policy_digest,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(PolicyNvWritten,
+ void(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNvWrittenResponse& callback));
+ MOCK_METHOD4(PolicyNvWrittenSync,
+ TPM_RC(const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(CreatePrimary,
+ void(const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ AuthorizationDelegate* authorization_delegate,
+ const CreatePrimaryResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC CreatePrimarySync(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD10(CreatePrimarySyncShort,
+ TPM_RC(const TPMI_RH_HIERARCHY& primary_handle,
+ const TPM2B_PUBLIC& in_public,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(HierarchyControl,
+ void(const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ AuthorizationDelegate* authorization_delegate,
+ const HierarchyControlResponse& callback));
+ MOCK_METHOD5(HierarchyControlSync,
+ TPM_RC(const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(SetPrimaryPolicy,
+ void(const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const SetPrimaryPolicyResponse& callback));
+ MOCK_METHOD5(SetPrimaryPolicySync,
+ TPM_RC(const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(ChangePPS,
+ void(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ChangePPSResponse& callback));
+ MOCK_METHOD3(ChangePPSSync,
+ TPM_RC(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(ChangeEPS,
+ void(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ChangeEPSResponse& callback));
+ MOCK_METHOD3(ChangeEPSSync,
+ TPM_RC(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(Clear,
+ void(const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ClearResponse& callback));
+ MOCK_METHOD3(ClearSync,
+ TPM_RC(const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(ClearControl,
+ void(const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ AuthorizationDelegate* authorization_delegate,
+ const ClearControlResponse& callback));
+ MOCK_METHOD4(ClearControlSync,
+ TPM_RC(const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(HierarchyChangeAuth,
+ void(const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const HierarchyChangeAuthResponse& callback));
+ MOCK_METHOD4(HierarchyChangeAuthSync,
+ TPM_RC(const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(DictionaryAttackLockReset,
+ void(const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const DictionaryAttackLockResetResponse& callback));
+ MOCK_METHOD3(DictionaryAttackLockResetSync,
+ TPM_RC(const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(DictionaryAttackParameters,
+ void(const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ AuthorizationDelegate* authorization_delegate,
+ const DictionaryAttackParametersResponse& callback));
+ MOCK_METHOD6(DictionaryAttackParametersSync,
+ TPM_RC(const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(PP_Commands,
+ void(const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate,
+ const PP_CommandsResponse& callback));
+ MOCK_METHOD5(PP_CommandsSync,
+ TPM_RC(const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(SetAlgorithmSet,
+ void(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ AuthorizationDelegate* authorization_delegate,
+ const SetAlgorithmSetResponse& callback));
+ MOCK_METHOD4(SetAlgorithmSetSync,
+ TPM_RC(const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(FieldUpgradeStart,
+ void(const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ AuthorizationDelegate* authorization_delegate,
+ const FieldUpgradeStartResponse& callback));
+ MOCK_METHOD7(FieldUpgradeStartSync,
+ TPM_RC(const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(FieldUpgradeData,
+ void(const TPM2B_MAX_BUFFER& fu_data,
+ AuthorizationDelegate* authorization_delegate,
+ const FieldUpgradeDataResponse& callback));
+ MOCK_METHOD4(FieldUpgradeDataSync,
+ TPM_RC(const TPM2B_MAX_BUFFER& fu_data,
+ TPMT_HA* next_digest,
+ TPMT_HA* first_digest,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(FirmwareRead,
+ void(const UINT32& sequence_number,
+ AuthorizationDelegate* authorization_delegate,
+ const FirmwareReadResponse& callback));
+ MOCK_METHOD3(FirmwareReadSync,
+ TPM_RC(const UINT32& sequence_number,
+ TPM2B_MAX_BUFFER* fu_data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(ContextSave,
+ void(const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ContextSaveResponse& callback));
+ MOCK_METHOD4(ContextSaveSync,
+ TPM_RC(const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ TPMS_CONTEXT* context,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(ContextLoad,
+ void(const TPMS_CONTEXT& context,
+ AuthorizationDelegate* authorization_delegate,
+ const ContextLoadResponse& callback));
+ MOCK_METHOD3(ContextLoadSync,
+ TPM_RC(const TPMS_CONTEXT& context,
+ TPMI_DH_CONTEXT* loaded_handle,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(FlushContext,
+ void(const TPMI_DH_CONTEXT& flush_handle,
+ AuthorizationDelegate* authorization_delegate,
+ const FlushContextResponse& callback));
+ MOCK_METHOD2(FlushContextSync,
+ TPM_RC(const TPMI_DH_CONTEXT& flush_handle,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(EvictControl,
+ void(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ AuthorizationDelegate* authorization_delegate,
+ const EvictControlResponse& callback));
+ MOCK_METHOD6(EvictControlSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD2(ReadClock,
+ void(AuthorizationDelegate* authorization_delegate,
+ const ReadClockResponse& callback));
+ MOCK_METHOD2(ReadClockSync,
+ TPM_RC(TPMS_TIME_INFO* current_time,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(ClockSet,
+ void(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ AuthorizationDelegate* authorization_delegate,
+ const ClockSetResponse& callback));
+ MOCK_METHOD4(ClockSetSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(ClockRateAdjust,
+ void(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ AuthorizationDelegate* authorization_delegate,
+ const ClockRateAdjustResponse& callback));
+ MOCK_METHOD4(ClockRateAdjustSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(GetCapability,
+ void(const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ AuthorizationDelegate* authorization_delegate,
+ const GetCapabilityResponse& callback));
+ MOCK_METHOD6(GetCapabilitySync,
+ TPM_RC(const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ TPMI_YES_NO* more_data,
+ TPMS_CAPABILITY_DATA* capability_data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD3(TestParms,
+ void(const TPMT_PUBLIC_PARMS& parameters,
+ AuthorizationDelegate* authorization_delegate,
+ const TestParmsResponse& callback));
+ MOCK_METHOD2(TestParmsSync,
+ TPM_RC(const TPMT_PUBLIC_PARMS& parameters,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(NV_DefineSpace,
+ void(const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_DefineSpaceResponse& callback));
+ MOCK_METHOD5(NV_DefineSpaceSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(NV_UndefineSpace,
+ void(const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_UndefineSpaceResponse& callback));
+ MOCK_METHOD5(NV_UndefineSpaceSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(NV_UndefineSpaceSpecial,
+ void(const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_UndefineSpaceSpecialResponse& callback));
+ MOCK_METHOD5(NV_UndefineSpaceSpecialSync,
+ TPM_RC(const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(NV_ReadPublic,
+ void(const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadPublicResponse& callback));
+ MOCK_METHOD5(NV_ReadPublicSync,
+ TPM_RC(const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ TPM2B_NV_PUBLIC* nv_public,
+ TPM2B_NAME* nv_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(NV_Write,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_WriteResponse& callback));
+ MOCK_METHOD7(NV_WriteSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(NV_Increment,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_IncrementResponse& callback));
+ MOCK_METHOD5(NV_IncrementSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(NV_Extend,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ExtendResponse& callback));
+ MOCK_METHOD6(NV_ExtendSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD7(NV_SetBits,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_SetBitsResponse& callback));
+ MOCK_METHOD6(NV_SetBitsSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(NV_WriteLock,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_WriteLockResponse& callback));
+ MOCK_METHOD5(NV_WriteLockSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD4(NV_GlobalWriteLock,
+ void(const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_GlobalWriteLockResponse& callback));
+ MOCK_METHOD3(NV_GlobalWriteLockSync,
+ TPM_RC(const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD8(NV_Read,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadResponse& callback));
+ MOCK_METHOD8(NV_ReadSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_MAX_NV_BUFFER* data,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD6(NV_ReadLock,
+ void(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadLockResponse& callback));
+ MOCK_METHOD5(NV_ReadLockSync,
+ TPM_RC(const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate));
+ MOCK_METHOD5(NV_ChangeAuth,
+ void(const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ChangeAuthResponse& callback));
+ MOCK_METHOD4(NV_ChangeAuthSync,
+ TPM_RC(const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate));
+ // Too many args to mock, forward to *Short version.
+ void NV_Certify(const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_CertifyResponse& callback) override;
+ MOCK_METHOD9(NV_CertifyShort,
+ void(const TPMI_DH_OBJECT& sign_handle,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_CertifyResponse& callback));
+ // Too many args to mock, forward to *Short version.
+ TPM_RC NV_CertifySync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) override;
+ MOCK_METHOD10(NV_CertifySyncShort,
+ TPM_RC(const TPMI_DH_OBJECT& sign_handle,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate));
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_TPM_H_
diff --git a/trunks/mock_tpm_state.cc b/trunks/mock_tpm_state.cc
new file mode 100644
index 0000000..ee52e3b
--- /dev/null
+++ b/trunks/mock_tpm_state.cc
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_tpm_state.h"
+
+#include <gmock/gmock.h>
+
+using testing::Return;
+
+namespace trunks {
+
+MockTpmState::MockTpmState() {
+ ON_CALL(*this, IsOwnerPasswordSet()).WillByDefault(Return(true));
+ ON_CALL(*this, IsEndorsementPasswordSet()).WillByDefault(Return(true));
+ ON_CALL(*this, IsLockoutPasswordSet()).WillByDefault(Return(true));
+ ON_CALL(*this, IsOwned()).WillByDefault(Return(true));
+ ON_CALL(*this, IsPlatformHierarchyEnabled()).WillByDefault(Return(true));
+ ON_CALL(*this, IsStorageHierarchyEnabled()).WillByDefault(Return(true));
+ ON_CALL(*this, IsEndorsementHierarchyEnabled()).WillByDefault(Return(true));
+ ON_CALL(*this, IsEnabled()).WillByDefault(Return(true));
+ ON_CALL(*this, WasShutdownOrderly()).WillByDefault(Return(true));
+ ON_CALL(*this, IsRSASupported()).WillByDefault(Return(true));
+ ON_CALL(*this, IsECCSupported()).WillByDefault(Return(true));
+ ON_CALL(*this, GetLockoutCounter()).WillByDefault(Return(0));
+ ON_CALL(*this, GetLockoutThreshold()).WillByDefault(Return(0));
+ ON_CALL(*this, GetLockoutInterval()).WillByDefault(Return(0));
+ ON_CALL(*this, GetLockoutRecovery()).WillByDefault(Return(0));
+}
+
+MockTpmState::~MockTpmState() {}
+
+} // namespace trunks
diff --git a/trunks/mock_tpm_state.h b/trunks/mock_tpm_state.h
new file mode 100644
index 0000000..9c3073a
--- /dev/null
+++ b/trunks/mock_tpm_state.h
@@ -0,0 +1,52 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_TPM_STATE_H_
+#define TRUNKS_MOCK_TPM_STATE_H_
+
+#include <gmock/gmock.h>
+
+#include "trunks/tpm_state.h"
+
+namespace trunks {
+
+class MockTpmState : public TpmState {
+ public:
+ MockTpmState();
+ ~MockTpmState() override;
+
+ MOCK_METHOD0(Initialize, TPM_RC());
+ MOCK_METHOD0(IsOwnerPasswordSet, bool());
+ MOCK_METHOD0(IsEndorsementPasswordSet, bool());
+ MOCK_METHOD0(IsLockoutPasswordSet, bool());
+ MOCK_METHOD0(IsOwned, bool());
+ MOCK_METHOD0(IsInLockout, bool());
+ MOCK_METHOD0(IsPlatformHierarchyEnabled, bool());
+ MOCK_METHOD0(IsStorageHierarchyEnabled, bool());
+ MOCK_METHOD0(IsEndorsementHierarchyEnabled, bool());
+ MOCK_METHOD0(IsEnabled, bool());
+ MOCK_METHOD0(WasShutdownOrderly, bool());
+ MOCK_METHOD0(IsRSASupported, bool());
+ MOCK_METHOD0(IsECCSupported, bool());
+ MOCK_METHOD0(GetLockoutCounter, uint32_t());
+ MOCK_METHOD0(GetLockoutThreshold, uint32_t());
+ MOCK_METHOD0(GetLockoutInterval, uint32_t());
+ MOCK_METHOD0(GetLockoutRecovery, uint32_t());
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_TPM_STATE_H_
diff --git a/trunks/mock_tpm_utility.cc b/trunks/mock_tpm_utility.cc
new file mode 100644
index 0000000..9f06385
--- /dev/null
+++ b/trunks/mock_tpm_utility.cc
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/mock_tpm_utility.h"
+
+namespace trunks {
+
+MockTpmUtility::MockTpmUtility() {}
+MockTpmUtility::~MockTpmUtility() {}
+
+} // namespace trunks
diff --git a/trunks/mock_tpm_utility.h b/trunks/mock_tpm_utility.h
new file mode 100644
index 0000000..1fa7fce
--- /dev/null
+++ b/trunks/mock_tpm_utility.h
@@ -0,0 +1,133 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_MOCK_TPM_UTILITY_H_
+#define TRUNKS_MOCK_TPM_UTILITY_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "trunks/tpm_utility.h"
+
+namespace trunks {
+
+class MockTpmUtility : public TpmUtility {
+ public:
+ MockTpmUtility();
+ ~MockTpmUtility() override;
+
+ MOCK_METHOD0(Startup, TPM_RC());
+ MOCK_METHOD0(Clear, TPM_RC());
+ MOCK_METHOD0(Shutdown, void());
+ MOCK_METHOD0(InitializeTpm, TPM_RC());
+ MOCK_METHOD1(AllocatePCR, TPM_RC(const std::string&));
+ MOCK_METHOD3(TakeOwnership, TPM_RC(const std::string&,
+ const std::string&,
+ const std::string&));
+ MOCK_METHOD2(StirRandom, TPM_RC(const std::string&, AuthorizationDelegate*));
+ MOCK_METHOD3(GenerateRandom, TPM_RC(size_t,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD3(ExtendPCR,
+ TPM_RC(int, const std::string&, AuthorizationDelegate*));
+ MOCK_METHOD2(ReadPCR, TPM_RC(int, std::string*));
+ MOCK_METHOD6(AsymmetricEncrypt, TPM_RC(TPM_HANDLE,
+ TPM_ALG_ID,
+ TPM_ALG_ID,
+ const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD6(AsymmetricDecrypt, TPM_RC(TPM_HANDLE,
+ TPM_ALG_ID,
+ TPM_ALG_ID,
+ const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD6(Sign, TPM_RC(TPM_HANDLE,
+ TPM_ALG_ID,
+ TPM_ALG_ID,
+ const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD6(Verify, TPM_RC(TPM_HANDLE,
+ TPM_ALG_ID,
+ TPM_ALG_ID,
+ const std::string&,
+ const std::string&,
+ AuthorizationDelegate*));
+ MOCK_METHOD2(CertifyCreation, TPM_RC(TPM_HANDLE,
+ const std::string&));
+ MOCK_METHOD4(ChangeKeyAuthorizationData, TPM_RC(TPM_HANDLE,
+ const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD7(ImportRSAKey, TPM_RC(AsymmetricKeyUsage,
+ const std::string&,
+ uint32_t,
+ const std::string&,
+ const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD10(CreateRSAKeyPair, TPM_RC(AsymmetricKeyUsage,
+ int,
+ uint32_t,
+ const std::string&,
+ const std::string&,
+ bool,
+ int,
+ AuthorizationDelegate*,
+ std::string*,
+ std::string*));
+ MOCK_METHOD3(LoadKey, TPM_RC(const std::string&,
+ AuthorizationDelegate*,
+ TPM_HANDLE*));
+ MOCK_METHOD2(GetKeyName, TPM_RC(TPM_HANDLE, std::string*));
+ MOCK_METHOD2(GetKeyPublicArea, TPM_RC(TPM_HANDLE, TPMT_PUBLIC*));
+ MOCK_METHOD4(SealData, TPM_RC(const std::string&,
+ const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD3(UnsealData, TPM_RC(const std::string&,
+ AuthorizationDelegate*,
+ std::string*));
+ MOCK_METHOD1(StartSession, TPM_RC(HmacSession*));
+ MOCK_METHOD3(GetPolicyDigestForPcrValue, TPM_RC(int,
+ const std::string&,
+ std::string*));
+ MOCK_METHOD3(DefineNVSpace, TPM_RC(uint32_t,
+ size_t,
+ AuthorizationDelegate*));
+ MOCK_METHOD2(DestroyNVSpace, TPM_RC(uint32_t,
+ AuthorizationDelegate*));
+ MOCK_METHOD2(LockNVSpace, TPM_RC(uint32_t,
+ AuthorizationDelegate*));
+ MOCK_METHOD4(WriteNVSpace, TPM_RC(uint32_t,
+ uint32_t,
+ const std::string&,
+ AuthorizationDelegate*));
+ MOCK_METHOD5(ReadNVSpace, TPM_RC(uint32_t,
+ uint32_t,
+ size_t,
+ std::string*,
+ AuthorizationDelegate*));
+ MOCK_METHOD2(GetNVSpaceName, TPM_RC(uint32_t, std::string*));
+ MOCK_METHOD2(GetNVSpacePublicArea, TPM_RC(uint32_t, TPMS_NV_PUBLIC*));
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_MOCK_TPM_UTILITY_H_
diff --git a/trunks/org.chromium.Trunks.conf b/trunks/org.chromium.Trunks.conf
new file mode 100644
index 0000000..9700dfb
--- /dev/null
+++ b/trunks/org.chromium.Trunks.conf
@@ -0,0 +1,15 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy user="trunks">
+ <allow own="org.chromium.Trunks" />
+ </policy>
+
+ <policy context="default">
+ <allow send_destination="org.chromium.Trunks" />
+ <!-- introspection denied -->
+ <deny send_destination="org.chromium.Trunks"
+ send_interface="org.freedesktop.DBus.Introspectable" />
+ </policy>
+</busconfig>
diff --git a/trunks/password_authorization_delegate.cc b/trunks/password_authorization_delegate.cc
new file mode 100644
index 0000000..c8049a6
--- /dev/null
+++ b/trunks/password_authorization_delegate.cc
@@ -0,0 +1,95 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/password_authorization_delegate.h"
+
+#include <base/logging.h>
+
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+const uint8_t kContinueSession = 1;
+
+PasswordAuthorizationDelegate::PasswordAuthorizationDelegate(
+ const std::string& password) {
+ password_ = Make_TPM2B_DIGEST(password);
+}
+
+PasswordAuthorizationDelegate::~PasswordAuthorizationDelegate() {}
+
+bool PasswordAuthorizationDelegate::GetCommandAuthorization(
+ const std::string& command_hash,
+ bool is_command_parameter_encryption_possible,
+ bool is_response_parameter_encryption_possible,
+ std::string* authorization) {
+ TPMS_AUTH_COMMAND auth;
+ auth.session_handle = TPM_RS_PW;
+ auth.nonce.size = 0;
+ auth.session_attributes = kContinueSession;
+ auth.hmac = password_;
+
+ TPM_RC serialize_error = Serialize_TPMS_AUTH_COMMAND(auth, authorization);
+ if (serialize_error != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": could not serialize command auth.";
+ return false;
+ }
+ return true;
+}
+
+bool PasswordAuthorizationDelegate::CheckResponseAuthorization(
+ const std::string& response_hash,
+ const std::string& authorization) {
+ TPMS_AUTH_RESPONSE auth_response;
+ std::string mutable_auth_string(authorization);
+ std::string auth_bytes;
+ TPM_RC parse_error;
+ parse_error = Parse_TPMS_AUTH_RESPONSE(&mutable_auth_string, &auth_response,
+ &auth_bytes);
+ if (authorization.size() != auth_bytes.size()) {
+ LOG(ERROR) << __func__ << ": Authorization string was of wrong length.";
+ return false;
+ }
+ if (parse_error != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": could not parse authorization response.";
+ return false;
+ }
+ if (auth_response.nonce.size != 0) {
+ LOG(ERROR) << __func__ << ": received a non zero length nonce.";
+ return false;
+ }
+ if (auth_response.hmac.size != 0) {
+ LOG(ERROR) << __func__ << ": received a non zero length hmac.";
+ return false;
+ }
+ if (auth_response.session_attributes != kContinueSession) {
+ LOG(ERROR) << __func__ << ": received wrong session attributes.";
+ return false;
+ }
+ return true;
+}
+
+bool PasswordAuthorizationDelegate::EncryptCommandParameter(
+ std::string* parameter) {
+ return true;
+}
+
+bool PasswordAuthorizationDelegate::DecryptResponseParameter(
+ std::string* parameter) {
+ return true;
+}
+
+} // namespace trunks
diff --git a/trunks/password_authorization_delegate.h b/trunks/password_authorization_delegate.h
new file mode 100644
index 0000000..b8474c9
--- /dev/null
+++ b/trunks/password_authorization_delegate.h
@@ -0,0 +1,61 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_PASSWORD_AUTHORIZATION_DELEGATE_H_
+#define TRUNKS_PASSWORD_AUTHORIZATION_DELEGATE_H_
+
+#include <string>
+
+#include <base/gtest_prod_util.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+// PasswdAuthorizationDelegate is an implementation of the AuthorizationDelegate
+// interface. This delegate is used for password based authorization. Upon
+// initialization of this delegate, we feed in the plaintext password. This
+// password is then used to authorize the commands issued with this delegate.
+// This delegate performs no parameter encryption.
+class TRUNKS_EXPORT PasswordAuthorizationDelegate
+ : public AuthorizationDelegate {
+ public:
+ explicit PasswordAuthorizationDelegate(const std::string& password);
+ ~PasswordAuthorizationDelegate() override;
+ // AuthorizationDelegate methods.
+ bool GetCommandAuthorization(const std::string& command_hash,
+ bool is_command_parameter_encryption_possible,
+ bool is_response_parameter_encryption_possible,
+ std::string* authorization) override;
+ bool CheckResponseAuthorization(const std::string& response_hash,
+ const std::string& authorization) override;
+ bool EncryptCommandParameter(std::string* parameter) override;
+ bool DecryptResponseParameter(std::string* parameter) override;
+
+ protected:
+ FRIEND_TEST(PasswordAuthorizationDelegateTest, NullInitialization);
+
+ private:
+ TPM2B_AUTH password_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordAuthorizationDelegate);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_PASSWORD_AUTHORIZATION_DELEGATE_H_
diff --git a/trunks/password_authorization_delegate_test.cc b/trunks/password_authorization_delegate_test.cc
new file mode 100644
index 0000000..2bdcbb0
--- /dev/null
+++ b/trunks/password_authorization_delegate_test.cc
@@ -0,0 +1,96 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "trunks/password_authorization_delegate.h"
+
+namespace trunks {
+
+// This test looks at initialization of the delegate with no password.
+// It should initailize with a zero length internal password buffer.
+TEST(PasswordAuthorizationDelegateTest, NullInitialization) {
+ PasswordAuthorizationDelegate delegate("");
+ EXPECT_EQ(delegate.password_.size, 0);
+}
+
+// This test checks the generation of an authorization structure by the
+// delegate. It compared the serialized structure generated by the delegate
+// to the expected authorization string.
+TEST(PasswordAuthorizationDelegateTest, SerializationTest) {
+ std::string expected_auth("\x40\x00\x00\x09" // session_handle = TPM_RS_PW
+ "\x00\x00" // nonce = zero length buffer
+ "\x01" // session_attributes = continueSession
+ "\x00\x06" // password length
+ "secret", // password
+ 15);
+ PasswordAuthorizationDelegate delegate("secret");
+ std::string authorization;
+ std::string command_hash;
+ bool authorization_result = delegate.GetCommandAuthorization(command_hash,
+ false, false,
+ &authorization);
+ EXPECT_EQ(authorization_result, true);
+ EXPECT_EQ(authorization.length(), expected_auth.length());
+ EXPECT_EQ(expected_auth.compare(authorization), 0);
+}
+
+// This test looks at the delegate's ability to parse and check authorization
+// responses when the response is well formed.
+TEST(PasswordAuthorizationDelegateTest, ParseGoodParams) {
+ std::string auth_response("\x00\x00" // nonceTpm = zero length buffer
+ "\x01" // session_attributes = continueSession
+ "\x00\x00", // hmac = zero length buffer
+ 5);
+ PasswordAuthorizationDelegate delegate("secret");
+ std::string response_hash;
+ bool authorization_result = delegate.CheckResponseAuthorization(
+ response_hash,
+ auth_response);
+ EXPECT_EQ(authorization_result, true);
+}
+
+// This test checks the delegate's ability to correctly identify an incorrect
+// authorization response.
+TEST(PasswordAuthorizationDelegateTest, ParseBadParams) {
+ std::string auth_response("\x00\x00" // nonceTpm = zero length buffer
+ "\x01" // session_attributes = continueSession
+ "\x00\x06" // password length
+ "secret", // password
+ 11);
+ PasswordAuthorizationDelegate delegate("secret");
+ std::string response_hash;
+ bool authorization_result = delegate.CheckResponseAuthorization(
+ response_hash,
+ auth_response);
+ EXPECT_EQ(authorization_result, false);
+}
+
+// This test confirms that after encrypting and decrypting a parameter,
+// we get the original parameter back.
+TEST(PasswordAuthorizationDelegateTest, EncryptDecrypt) {
+ PasswordAuthorizationDelegate delegate("secret");
+ std::string plaintext_parameter("parameter");
+ std::string encrypted_parameter(plaintext_parameter);
+ ASSERT_EQ(plaintext_parameter.compare(encrypted_parameter), 0);
+ delegate.EncryptCommandParameter(&encrypted_parameter);
+ delegate.DecryptResponseParameter(&encrypted_parameter);
+ EXPECT_EQ(plaintext_parameter.compare(encrypted_parameter), 0);
+}
+
+} // namespace trunks
diff --git a/trunks/policy_session.h b/trunks/policy_session.h
new file mode 100644
index 0000000..a8d7d4b
--- /dev/null
+++ b/trunks/policy_session.h
@@ -0,0 +1,88 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_POLICY_SESSION_H_
+#define TRUNKS_POLICY_SESSION_H_
+
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+class AuthorizationDelegate;
+
+// PolicySession is an interface for managing policy backed sessions for
+// authorization and parameter encryption.
+class PolicySession {
+ public:
+ PolicySession() {}
+ virtual ~PolicySession() {}
+
+ // Returns an authorization delegate for this session. Ownership of the
+ // delegate pointer is retained by the session.
+ virtual AuthorizationDelegate* GetDelegate() = 0;
+
+ // Starts a salted session which is bound to |bind_entity| with
+ // |bind_authorization_value|. Encryption is enabled if |enable_encryption| is
+ // true. The session remains active until this object is destroyed or another
+ // session is started with a call to Start*Session.
+ virtual TPM_RC StartBoundSession(
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) = 0;
+
+ // Starts a salted, unbound session. Encryption is enabled if
+ // |enable_encryption| is true. The session remains active until this object
+ // is destroyed or another session is started with a call to Start*Session.
+ virtual TPM_RC StartUnboundSession(bool enable_encryption) = 0;
+
+ // This method is used to get the current PolicyDigest of the PolicySession.
+ virtual TPM_RC GetDigest(std::string* digest) = 0;
+
+ // This method is used to construct a complex policy. It takes a list
+ // of policy digests. After the command is executed, the policy represented
+ // by this session is the OR of the provided policies.
+ virtual TPM_RC PolicyOR(const std::vector<std::string>& digests) = 0;
+
+ // This method binds the PolicySession to a provided PCR value. If the empty
+ // string is provided, the PolicySession is bound to the current PCR value.
+ virtual TPM_RC PolicyPCR(uint32_t pcr_index,
+ const std::string& pcr_value) = 0;
+
+ // This method binds the PolicySession to a specified CommandCode.
+ // Once called, this Session can only be used to authorize actions on the
+ // provided CommandCode.
+ virtual TPM_RC PolicyCommandCode(TPM_CC command_code) = 0;
+
+ // This method specifies that Authorization Values need to be included in
+ // HMAC computation done by the AuthorizationDelegate.
+ virtual TPM_RC PolicyAuthValue() = 0;
+
+ // Sets the current entity authorization value. This can be safely called
+ // while the session is active and subsequent commands will use the value.
+ virtual void SetEntityAuthorizationValue(const std::string& value) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PolicySession);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_POLICY_SESSION_H_
diff --git a/trunks/policy_session_impl.cc b/trunks/policy_session_impl.cc
new file mode 100644
index 0000000..cb2c4e0
--- /dev/null
+++ b/trunks/policy_session_impl.cc
@@ -0,0 +1,184 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/policy_session_impl.h"
+
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+#include <base/macros.h>
+#include <base/stl_util.h>
+#include <crypto/sha2.h>
+#include <openssl/rand.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory)
+ : factory_(factory),
+ session_type_(TPM_SE_POLICY) {
+ session_manager_ = factory_.GetSessionManager();
+}
+
+PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory,
+ TPM_SE session_type)
+ : factory_(factory),
+ session_type_(session_type) {
+ session_manager_ = factory_.GetSessionManager();
+}
+
+PolicySessionImpl::~PolicySessionImpl() {
+ session_manager_->CloseSession();
+}
+
+AuthorizationDelegate* PolicySessionImpl::GetDelegate() {
+ if (session_manager_->GetSessionHandle() == kUninitializedHandle) {
+ return nullptr;
+ }
+ return &hmac_delegate_;
+}
+
+TPM_RC PolicySessionImpl::StartBoundSession(
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) {
+ hmac_delegate_.set_use_entity_authorization_for_encryption_only(true);
+ if (session_type_ != TPM_SE_POLICY && session_type_ != TPM_SE_TRIAL) {
+ LOG(ERROR) << "Cannot start a session of that type.";
+ return SAPI_RC_INVALID_SESSIONS;
+ }
+ return session_manager_->StartSession(session_type_, bind_entity,
+ bind_authorization_value,
+ enable_encryption, &hmac_delegate_);
+}
+
+TPM_RC PolicySessionImpl::StartUnboundSession(bool enable_encryption) {
+ // Just like a HmacAuthorizationSession, an unbound policy session is just
+ // a session bound to TPM_RH_NULL.
+ return StartBoundSession(TPM_RH_NULL, "", enable_encryption);
+}
+
+TPM_RC PolicySessionImpl::GetDigest(std::string* digest) {
+ CHECK(digest);
+ TPM2B_DIGEST policy_digest;
+ TPM_RC result = factory_.GetTpm()->PolicyGetDigestSync(
+ session_manager_->GetSessionHandle(),
+ "", // No name is needed for this command, as it does no authorization.
+ &policy_digest,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return result;
+ }
+ *digest = StringFrom_TPM2B_DIGEST(policy_digest);
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC PolicySessionImpl::PolicyOR(const std::vector<std::string>& digests) {
+ if (digests.size() >= arraysize(TPML_DIGEST::digests)) {
+ LOG(ERROR) << "TPM2.0 Spec only allows for up to 8 digests.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ TPML_DIGEST tpm_digests;
+ tpm_digests.count = digests.size();
+ for (size_t i = 0; i < digests.size(); i++) {
+ tpm_digests.digests[i] = Make_TPM2B_DIGEST(digests[i]);
+ }
+ TPM_RC result = factory_.GetTpm()->PolicyORSync(
+ session_manager_->GetSessionHandle(),
+ "", // No policy name is needed as we do no authorization checks.
+ tpm_digests,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error performing PolicyOR: " << GetErrorString(result);
+ return result;
+ }
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC PolicySessionImpl::PolicyPCR(uint32_t pcr_index,
+ const std::string& pcr_value) {
+ TPML_PCR_SELECTION pcr_select;
+ memset(&pcr_select, 0, sizeof(TPML_PCR_SELECTION));
+ // This process of selecting pcrs is highlighted in TPM 2.0 Library Spec
+ // Part 2 (Section 10.5 - PCR structures).
+ uint8_t pcr_select_index = pcr_index / 8;
+ uint8_t pcr_select_byte = 1 << (pcr_index % 8);
+ pcr_select.count = 1;
+ pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
+ pcr_select.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
+ pcr_select.pcr_selections[0].pcr_select[pcr_select_index] = pcr_select_byte;
+ TPM2B_DIGEST pcr_digest;
+ if (pcr_value.empty()) {
+ if (session_type_ == TPM_SE_TRIAL) {
+ LOG(ERROR) << "Trial sessions have to define a PCR value.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ pcr_digest = Make_TPM2B_DIGEST("");
+ } else {
+ pcr_digest = Make_TPM2B_DIGEST(crypto::SHA256HashString(pcr_value));
+ }
+
+ TPM_RC result = factory_.GetTpm()->PolicyPCRSync(
+ session_manager_->GetSessionHandle(),
+ "", // No policy name is needed as we do no authorization checks.
+ pcr_digest,
+ pcr_select,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error performing PolicyPCR: " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC PolicySessionImpl::PolicyCommandCode(TPM_CC command_code) {
+ TPM_RC result = factory_.GetTpm()->PolicyCommandCodeSync(
+ session_manager_->GetSessionHandle(),
+ "", // No policy name is needed as we do no authorization checks.
+ command_code,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error performing PolicyCommandCode: "
+ << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC PolicySessionImpl::PolicyAuthValue() {
+ TPM_RC result = factory_.GetTpm()->PolicyAuthValueSync(
+ session_manager_->GetSessionHandle(),
+ "", // No policy name is needed as we do no authorization checks.
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error performing PolicyAuthValue: "
+ << GetErrorString(result);
+ return result;
+ }
+ hmac_delegate_.set_use_entity_authorization_for_encryption_only(false);
+ return TPM_RC_SUCCESS;
+}
+
+void PolicySessionImpl::SetEntityAuthorizationValue(const std::string& value) {
+ hmac_delegate_.set_entity_authorization_value(value);
+}
+
+} // namespace trunks
diff --git a/trunks/policy_session_impl.h b/trunks/policy_session_impl.h
new file mode 100644
index 0000000..fc17f7b
--- /dev/null
+++ b/trunks/policy_session_impl.h
@@ -0,0 +1,85 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_POLICY_SESSION_IMPL_H_
+#define TRUNKS_POLICY_SESSION_IMPL_H_
+
+#include "trunks/policy_session.h"
+
+#include <string>
+#include <vector>
+
+#include "trunks/hmac_authorization_delegate.h"
+#include "trunks/session_manager.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+// This class implements the PolicySession interface. It is used for
+// keeping track of the HmacAuthorizationDelegate used for commands, and to
+// provide authorization for commands that need it. It can also be used to
+// create custom policies to restrict the usage of keys.
+// TrunksFactoryImpl factory;
+// PolicySessionImpl session(factory);
+// session.StartBoundSession(bind_entity, bind_authorization, true);
+// session.PolicyPCR(pcr_index, pcr_value);
+// factory.GetTpm()->RSA_EncrpytSync(_,_,_,_, session.GetDelegate());
+// NOTE: StartBoundSession/StartUnboundSession should not be called before
+// TPM Ownership is taken. This is because starting a session uses the
+// SaltingKey, which is only created after ownership is taken.
+class TRUNKS_EXPORT PolicySessionImpl: public PolicySession {
+ public:
+ explicit PolicySessionImpl(const TrunksFactory& factory);
+ // |session_type| specifies what type of session this is. It can only
+ // be TPM_SE_TRIAL or TPM_SE_POLICY. If other values are used,
+ // StartBoundSession will return SAPI_RC_INVALID_SESSIONS.
+ PolicySessionImpl(const TrunksFactory& factory, TPM_SE session_type);
+ ~PolicySessionImpl() override;
+
+ // PolicySession methods
+ AuthorizationDelegate* GetDelegate() override;
+ TPM_RC StartBoundSession(TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) override;
+ TPM_RC StartUnboundSession(bool enable_encryption) override;
+ TPM_RC GetDigest(std::string* digest) override;
+ TPM_RC PolicyOR(const std::vector<std::string>& digests) override;
+ TPM_RC PolicyPCR(uint32_t pcr_index, const std::string& pcr_value) override;
+ TPM_RC PolicyCommandCode(TPM_CC command_code) override;
+ TPM_RC PolicyAuthValue() override;
+ void SetEntityAuthorizationValue(const std::string& value) override;
+
+ private:
+ // This factory is only set in the constructor and is used to instantiate
+ // The TPM class to forward commands to the TPM chip.
+ const TrunksFactory& factory_;
+ // This field determines if this session is of type TPM_SE_TRIAL or
+ // TPM_SE_POLICY.
+ TPM_SE session_type_;
+ // This delegate is what provides authorization to commands. It is what is
+ // returned when the GetDelegate method is called.
+ HmacAuthorizationDelegate hmac_delegate_;
+ // This object is used to manage the TPM session associated with this
+ // AuthorizationSession.
+ scoped_ptr<SessionManager> session_manager_;
+
+ friend class PolicySessionTest;
+ DISALLOW_COPY_AND_ASSIGN(PolicySessionImpl);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_POLICY_SESSION_IMPL_H_
diff --git a/trunks/policy_session_test.cc b/trunks/policy_session_test.cc
new file mode 100644
index 0000000..c2d93e8
--- /dev/null
+++ b/trunks/policy_session_test.cc
@@ -0,0 +1,229 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/policy_session_impl.h"
+
+#include <crypto/sha2.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/mock_session_manager.h"
+#include "trunks/mock_tpm.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+using testing::SaveArg;
+using testing::SetArgPointee;
+
+namespace trunks {
+
+class PolicySessionTest : public testing::Test {
+ public:
+ PolicySessionTest() {}
+ ~PolicySessionTest() override {}
+
+ void SetUp() override {
+ factory_.set_session_manager(&mock_session_manager_);
+ factory_.set_tpm(&mock_tpm_);
+ }
+
+ HmacAuthorizationDelegate* GetHmacDelegate(PolicySessionImpl* session) {
+ return &(session->hmac_delegate_);
+ }
+
+ protected:
+ TrunksFactoryForTest factory_;
+ NiceMock<MockSessionManager> mock_session_manager_;
+ NiceMock<MockTpm> mock_tpm_;
+};
+
+TEST_F(PolicySessionTest, GetDelegateUninitialized) {
+ PolicySessionImpl session(factory_);
+ EXPECT_CALL(mock_session_manager_, GetSessionHandle())
+ .WillRepeatedly(Return(kUninitializedHandle));
+ EXPECT_EQ(nullptr, session.GetDelegate());
+}
+
+TEST_F(PolicySessionTest, GetDelegateSuccess) {
+ PolicySessionImpl session(factory_);
+ EXPECT_EQ(GetHmacDelegate(&session), session.GetDelegate());
+}
+
+TEST_F(PolicySessionTest, StartBoundSessionSuccess) {
+ PolicySessionImpl session(factory_);
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ session.StartBoundSession(TPM_RH_FIRST, "auth", true));
+}
+
+TEST_F(PolicySessionTest, StartBoundSessionFailure) {
+ PolicySessionImpl session(factory_);
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ EXPECT_CALL(mock_session_manager_, StartSession(TPM_SE_POLICY, handle,
+ _, true, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.StartBoundSession(handle, "auth", true));
+}
+
+TEST_F(PolicySessionTest, StartBoundSessionBadType) {
+ PolicySessionImpl session(factory_, TPM_SE_HMAC);
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS,
+ session.StartBoundSession(TPM_RH_FIRST, "auth", true));
+}
+
+TEST_F(PolicySessionTest, StartUnboundSessionSuccess) {
+ PolicySessionImpl session(factory_);
+ EXPECT_EQ(TPM_RC_SUCCESS, session.StartUnboundSession(true));
+}
+
+TEST_F(PolicySessionTest, StartUnboundSessionFailure) {
+ PolicySessionImpl session(factory_);
+ EXPECT_CALL(mock_session_manager_, StartSession(TPM_SE_POLICY, TPM_RH_NULL,
+ _, true, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.StartUnboundSession(true));
+}
+
+TEST_F(PolicySessionTest, GetDigestSuccess) {
+ PolicySessionImpl session(factory_);
+ std::string digest;
+ TPM2B_DIGEST policy_digest;
+ policy_digest.size = SHA256_DIGEST_SIZE;
+ EXPECT_CALL(mock_tpm_, PolicyGetDigestSync(_, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<2>(policy_digest),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, session.GetDigest(&digest));
+ EXPECT_EQ(SHA256_DIGEST_SIZE, digest.size());
+}
+
+TEST_F(PolicySessionTest, GetDigestFailure) {
+ PolicySessionImpl session(factory_);
+ std::string digest;
+ EXPECT_CALL(mock_tpm_, PolicyGetDigestSync(_, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.GetDigest(&digest));
+}
+
+TEST_F(PolicySessionTest, PolicyORSuccess) {
+ PolicySessionImpl session(factory_);
+ std::vector<std::string> digests;
+ digests.push_back("digest1");
+ digests.push_back("digest2");
+ digests.push_back("digest3");
+ TPML_DIGEST tpm_digests;
+ EXPECT_CALL(mock_tpm_, PolicyORSync(_, _, _, _))
+ .WillOnce(DoAll(SaveArg<2>(&tpm_digests),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, session.PolicyOR(digests));
+ EXPECT_EQ(tpm_digests.count, digests.size());
+ EXPECT_EQ(StringFrom_TPM2B_DIGEST(tpm_digests.digests[0]), digests[0]);
+ EXPECT_EQ(StringFrom_TPM2B_DIGEST(tpm_digests.digests[1]), digests[1]);
+ EXPECT_EQ(StringFrom_TPM2B_DIGEST(tpm_digests.digests[2]), digests[2]);
+}
+
+TEST_F(PolicySessionTest, PolicyORBadParam) {
+ PolicySessionImpl session(factory_);
+ std::vector<std::string> digests;
+ // We use 9 here because the maximum number of digests allowed by the TPM
+ // is 8. Therefore having 9 digests here should cause the code to fail.
+ digests.resize(9);
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, session.PolicyOR(digests));
+}
+
+TEST_F(PolicySessionTest, PolicyORFailure) {
+ PolicySessionImpl session(factory_);
+ std::vector<std::string> digests;
+ EXPECT_CALL(mock_tpm_, PolicyORSync(_, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.PolicyOR(digests));
+}
+
+TEST_F(PolicySessionTest, PolicyPCRSuccess) {
+ PolicySessionImpl session(factory_);
+ std::string pcr_digest("digest");
+ int pcr_index = 1;
+ TPML_PCR_SELECTION pcr_select;
+ TPM2B_DIGEST pcr_value;
+ EXPECT_CALL(mock_tpm_, PolicyPCRSync(_, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<2>(&pcr_value),
+ SaveArg<3>(&pcr_select),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, session.PolicyPCR(pcr_index, pcr_digest));
+ uint8_t pcr_select_index = pcr_index / 8;
+ uint8_t pcr_select_byte = 1 << (pcr_index % 8);
+ EXPECT_EQ(pcr_select.count, 1);
+ EXPECT_EQ(pcr_select.pcr_selections[0].hash, TPM_ALG_SHA256);
+ EXPECT_EQ(pcr_select.pcr_selections[0].sizeof_select, PCR_SELECT_MIN);
+ EXPECT_EQ(pcr_select.pcr_selections[0].pcr_select[pcr_select_index],
+ pcr_select_byte);
+ EXPECT_EQ(StringFrom_TPM2B_DIGEST(pcr_value),
+ crypto::SHA256HashString(pcr_digest));
+}
+
+TEST_F(PolicySessionTest, PolicyPCRFailure) {
+ PolicySessionImpl session(factory_);
+ EXPECT_CALL(mock_tpm_, PolicyPCRSync(_, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.PolicyPCR(1, "pcr_digest"));
+}
+
+TEST_F(PolicySessionTest, PolicyPCRTrialWithNoDigest) {
+ PolicySessionImpl session(factory_, TPM_SE_TRIAL);
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, session.PolicyPCR(1, ""));
+}
+
+TEST_F(PolicySessionTest, PolicyCommandCodeSuccess) {
+ PolicySessionImpl session(factory_);
+ TPM_CC command_code = TPM_CC_FIRST;
+ EXPECT_CALL(mock_tpm_, PolicyCommandCodeSync(_, _, command_code, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, session.PolicyCommandCode(TPM_CC_FIRST));
+}
+
+TEST_F(PolicySessionTest, PolicyCommandCodeFailure) {
+ PolicySessionImpl session(factory_);
+ EXPECT_CALL(mock_tpm_, PolicyCommandCodeSync(_, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.PolicyCommandCode(TPM_CC_FIRST));
+}
+
+TEST_F(PolicySessionTest, PolicyAuthValueSuccess) {
+ PolicySessionImpl session(factory_);
+ EXPECT_CALL(mock_tpm_, PolicyAuthValueSync(_, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, session.PolicyAuthValue());
+}
+
+TEST_F(PolicySessionTest, PolicyAuthValueFailure) {
+ PolicySessionImpl session(factory_);
+ EXPECT_CALL(mock_tpm_, PolicyAuthValueSync(_, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session.PolicyAuthValue());
+}
+
+TEST_F(PolicySessionTest, EntityAuthorizationForwardingTest) {
+ PolicySessionImpl session(factory_);
+ std::string test_auth("test_auth");
+ session.SetEntityAuthorizationValue(test_auth);
+ HmacAuthorizationDelegate* hmac_delegate = GetHmacDelegate(&session);
+ std::string entity_auth = hmac_delegate->entity_authorization_value();
+ EXPECT_EQ(0, test_auth.compare(entity_auth));
+}
+
+} // namespace trunks
diff --git a/trunks/resource_manager.cc b/trunks/resource_manager.cc
new file mode 100644
index 0000000..5955d97
--- /dev/null
+++ b/trunks/resource_manager.cc
@@ -0,0 +1,856 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/resource_manager.h"
+
+#include <algorithm>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <base/callback.h>
+
+#include "trunks/error_codes.h"
+
+namespace {
+
+const int kMaxCommandAttempts = 3;
+const size_t kMinimumAuthorizationSize = 9;
+const size_t kMessageHeaderSize = 10;
+const trunks::TPM_HANDLE kMaxVirtualHandle =
+ (trunks::HR_TRANSIENT + trunks::HR_HANDLE_MASK);
+
+class ScopedBool {
+ public:
+ ScopedBool() : target_(nullptr) {}
+ ~ScopedBool() {
+ if (target_) {
+ *target_ = false;
+ }
+ }
+ void Enable(bool* target) {
+ target_ = target;
+ *target_ = true;
+ }
+ private:
+ bool* target_;
+};
+
+} // namespace
+
+namespace trunks {
+
+ResourceManager::ResourceManager(const TrunksFactory& factory,
+ CommandTransceiver* next_transceiver)
+ : factory_(factory),
+ next_transceiver_(next_transceiver) {}
+
+ResourceManager::~ResourceManager() {}
+
+void ResourceManager::Initialize() {
+ TPM_RC result = factory_.GetTpm()->StartupSync(TPM_SU_CLEAR, nullptr);
+ // Ignore TPM_RC_INITIALIZE, that means it was already started.
+ if (result != TPM_RC_SUCCESS && result != TPM_RC_INITIALIZE) {
+ LOG(ERROR) << "TPM startup failure: " << GetErrorString(result);
+ exit(-1);
+ }
+ result = factory_.GetTpm()->SelfTestSync(YES /* Full test. */, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "TPM self-test failure: " << GetErrorString(result);
+ exit(-1);
+ }
+ // Full control of the TPM is assumed and required. Existing transient object
+ // and session handles are mercilessly flushed.
+ for (UINT32 handle_type : {HR_TRANSIENT,
+ HR_HMAC_SESSION,
+ HR_POLICY_SESSION}) {
+ TPMI_YES_NO more_data = YES;
+ TPMS_CAPABILITY_DATA data;
+ UINT32 handle_range = handle_type;
+ while (more_data) {
+ result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_HANDLES,
+ handle_range,
+ MAX_CAP_HANDLES,
+ &more_data,
+ &data,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to query existing handles: "
+ << GetErrorString(result);
+ break;
+ }
+ const TPML_HANDLE& handle_list = data.data.handles;
+ for (UINT32 i = 0; i < handle_list.count; ++i) {
+ factory_.GetTpm()->FlushContextSync(handle_list.handle[i], nullptr);
+ }
+ if (more_data) {
+ // Adjust the range to be greater than the most recent handle so on the
+ // next query we'll start where we left off.
+ handle_range = handle_list.handle[handle_list.count-1];
+ }
+ }
+ }
+}
+
+void ResourceManager::SendCommand(
+ const std::string& command,
+ const ResponseCallback& callback) {
+ callback.Run(SendCommandAndWait(command));
+}
+
+std::string ResourceManager::SendCommandAndWait(const std::string& command) {
+ // Sanitize the |command|. If this succeeds consistency of the command header
+ // and the size of all other sections can be assumed.
+ MessageInfo command_info;
+ TPM_RC result = ParseCommand(command, &command_info);
+ if (result != TPM_RC_SUCCESS) {
+ return CreateErrorResponse(result);
+ }
+ // A special case for FlushContext. It requires special handling because it
+ // has a handle as a parameter and because we need to cleanup if it succeeds.
+ if (command_info.code == TPM_CC_FlushContext) {
+ return ProcessFlushContext(command, command_info);
+ }
+ // Process all the input handles, e.g. map virtual handles.
+ std::vector<TPM_HANDLE> updated_handles;
+ for (auto handle : command_info.handles) {
+ TPM_HANDLE tpm_handle;
+ result = ProcessInputHandle(command_info, handle, &tpm_handle);
+ if (result != TPM_RC_SUCCESS) {
+ return CreateErrorResponse(result);
+ }
+ updated_handles.push_back(tpm_handle);
+ }
+ std::string updated_command = ReplaceHandles(command, updated_handles);
+ // Make sure all the required sessions are loaded.
+ for (auto handle : command_info.session_handles) {
+ result = EnsureSessionIsLoaded(command_info, handle);
+ if (result != TPM_RC_SUCCESS) {
+ return CreateErrorResponse(result);
+ }
+ }
+ // On a ContextLoad we may need to map virtualized context data.
+ if (command_info.code == TPM_CC_ContextLoad) {
+ std::string actual_load_data = GetActualContextFromExternalContext(
+ command_info.parameter_data);
+ // Check equality to see if replacement is necessary, and check size to see
+ // if the command looks like we expect (the idea is to avoid 'fixing'
+ // malformed commands). Note: updated_command.size() is guaranteed to be >=
+ // kMessageHeaderSize based on the sanitization in ParseCommand.
+ if (actual_load_data != command_info.parameter_data &&
+ actual_load_data.size() ==
+ updated_command.size() - kMessageHeaderSize) {
+ // Replace the parameter section of the command with |actual_load_data|.
+ VLOG(1) << "REPLACE_EXTERNAL_CONTEXT";
+ updated_command.replace(kMessageHeaderSize, std::string::npos,
+ actual_load_data);
+ }
+ }
+ // Send the |updated_command| to the next layer. Attempt to fix any actionable
+ // warnings for up to kMaxCommandAttempts.
+ std::string response;
+ MessageInfo response_info;
+ int attempts = 0;
+ while (attempts++ < kMaxCommandAttempts) {
+ response = next_transceiver_->SendCommandAndWait(updated_command);
+ result = ParseResponse(command_info, response, &response_info);
+ if (result != TPM_RC_SUCCESS) {
+ return CreateErrorResponse(result);
+ }
+ if (!FixWarnings(command_info, response_info.code)) {
+ // No actionable warnings were handled.
+ break;
+ }
+ }
+ if (response_info.code == TPM_RC_SUCCESS) {
+ if (response_info.session_continued.size() !=
+ command_info.session_handles.size()) {
+ LOG(WARNING) << "Session count mismatch!";
+ }
+ // Cleanup any sessions that were not continued.
+ for (size_t i = 0; i < command_info.session_handles.size(); ++i) {
+ if (i < response_info.session_continued.size() &&
+ !response_info.session_continued[i]) {
+ CleanupFlushedHandle(command_info.session_handles[i]);
+ }
+ }
+ // On a successful context save we need to cache the context data in case it
+ // needs to be virtualized later.
+ if (command_info.code == TPM_CC_ContextSave) {
+ ProcessExternalContextSave(command_info, response_info);
+ }
+ // Process all the output handles, which is loosely the inverse of the input
+ // handle processing. E.g. virtualize handles.
+ std::vector<TPM_HANDLE> virtual_handles;
+ for (auto handle : response_info.handles) {
+ virtual_handles.push_back(ProcessOutputHandle(handle));
+ }
+ response = ReplaceHandles(response, virtual_handles);
+ }
+ return response;
+}
+
+bool ResourceManager::ChooseSessionToEvict(
+ const std::vector<TPM_HANDLE>& sessions_to_retain,
+ TPM_HANDLE* session_to_evict) {
+ // Build a list of candidates by excluding |sessions_to_retain|.
+ std::vector<TPM_HANDLE> candidates;
+ for (auto& item : session_handles_) {
+ HandleInfo& info = item.second;
+ if (info.is_loaded &&
+ std::find(sessions_to_retain.begin(),
+ sessions_to_retain.end(),
+ info.tpm_handle) == sessions_to_retain.end()) {
+ candidates.push_back(item.first);
+ }
+ }
+ if (candidates.empty()) {
+ LOG(WARNING) << "No sessions to evict.";
+ return false;
+ }
+ // Choose the candidate with the earliest |time_of_last_use|.
+ auto oldest_iter = std::min_element(
+ candidates.begin(), candidates.end(),
+ [this](TPM_HANDLE a, TPM_HANDLE b) {
+ return (session_handles_[a].time_of_last_use <
+ session_handles_[b].time_of_last_use);
+ });
+ *session_to_evict = *oldest_iter;
+ return true;
+}
+
+void ResourceManager::CleanupFlushedHandle(TPM_HANDLE flushed_handle) {
+ if (IsObjectHandle(flushed_handle)) {
+ // For transient object handles, remove both the actual and virtual handles.
+ if (virtual_object_handles_.count(flushed_handle) > 0) {
+ tpm_object_handles_.erase(
+ virtual_object_handles_[flushed_handle].tpm_handle);
+ virtual_object_handles_.erase(flushed_handle);
+ }
+ } else if (IsSessionHandle(flushed_handle)) {
+ auto iter = session_handles_.find(flushed_handle);
+ if (iter == session_handles_.end()) {
+ return;
+ }
+ // For session handles, remove the handle and any associated context data.
+ HandleInfo& info = iter->second;
+ if (!info.is_loaded) {
+ std::string actual_context_data;
+ Serialize_TPMS_CONTEXT(info.context, &actual_context_data);
+ if (actual_context_to_external_.count(actual_context_data) > 0) {
+ external_context_to_actual_.erase(
+ actual_context_to_external_[actual_context_data]);
+ actual_context_to_external_.erase(actual_context_data);
+ }
+ }
+ session_handles_.erase(flushed_handle);
+ VLOG(1) << "CLEANUP_SESSION: " << std::hex << flushed_handle;
+ }
+}
+
+TPM_HANDLE ResourceManager::CreateVirtualHandle() {
+ TPM_HANDLE handle;
+ do {
+ handle = next_virtual_handle_;
+ if (next_virtual_handle_ == kMaxVirtualHandle) {
+ next_virtual_handle_ = TRANSIENT_FIRST;
+ } else {
+ ++next_virtual_handle_;
+ }
+ } while (virtual_object_handles_.count(handle) > 0);
+ return handle;
+}
+
+TPM_RC ResourceManager::EnsureSessionIsLoaded(const MessageInfo& command_info,
+ TPM_HANDLE session_handle) {
+ // A password authorization can skip all this.
+ if (session_handle == TPM_RS_PW) {
+ return TPM_RC_SUCCESS;
+ }
+ auto handle_iter = session_handles_.find(session_handle);
+ if (handle_iter == session_handles_.end()) {
+ return MakeError(TPM_RC_HANDLE, FROM_HERE);
+ }
+ HandleInfo& handle_info = handle_iter->second;
+ if (!handle_info.is_loaded) {
+ TPM_RC result = LoadContext(command_info, &handle_info);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ VLOG(1) << "RELOAD_SESSION: " << std::hex << session_handle;
+ }
+ handle_info.time_of_last_use = base::TimeTicks::Now();
+ return TPM_RC_SUCCESS;
+}
+
+void ResourceManager::EvictObjects(const MessageInfo& command_info) {
+ for (auto& item : virtual_object_handles_) {
+ HandleInfo& info = item.second;
+ if (!info.is_loaded ||
+ std::find(command_info.handles.begin(),
+ command_info.handles.end(),
+ item.first) != command_info.handles.end()) {
+ continue;
+ }
+ TPM_RC result = SaveContext(command_info, &info);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to save transient object: "
+ << GetErrorString(result);
+ continue;
+ }
+ result = factory_.GetTpm()->FlushContextSync(info.tpm_handle, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to evict transient object: "
+ << GetErrorString(result);
+ continue;
+ }
+ tpm_object_handles_.erase(info.tpm_handle);
+ VLOG(1) << "EVICT_OBJECT: " << std::hex << info.tpm_handle;
+ }
+}
+
+void ResourceManager::EvictSession(const MessageInfo& command_info) {
+ TPM_HANDLE session_to_evict;
+ if (!ChooseSessionToEvict(command_info.session_handles, &session_to_evict)) {
+ return;
+ }
+ HandleInfo& info = session_handles_[session_to_evict];
+ TPM_RC result = SaveContext(command_info, &info);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to evict session: " << GetErrorString(result);
+ }
+ VLOG(1) << "EVICT_SESSION: " << std::hex << session_to_evict;
+}
+
+std::vector<TPM_HANDLE> ResourceManager::ExtractHandlesFromBuffer(
+ size_t number_of_handles,
+ std::string* buffer) {
+ std::vector<TPM_HANDLE> handles(number_of_handles);
+ for (size_t i = 0; i < number_of_handles; ++i) {
+ TPM_HANDLE handle;
+ if (TPM_RC_SUCCESS == Parse_TPM_HANDLE(buffer, &handle, nullptr)) {
+ handles[i] = handle;
+ }
+ }
+ return handles;
+}
+
+void ResourceManager::FixContextGap(const MessageInfo& command_info) {
+ std::vector<TPM_HANDLE> sessions_to_ungap;
+ for (const auto& item : session_handles_) {
+ const HandleInfo& info = item.second;
+ if (!info.is_loaded) {
+ sessions_to_ungap.push_back(item.first);
+ }
+ }
+ // Sort by |time_of_create|.
+ std::sort(sessions_to_ungap.begin(), sessions_to_ungap.end(),
+ [this](TPM_HANDLE a, TPM_HANDLE b) {
+ return (session_handles_[a].time_of_create <
+ session_handles_[b].time_of_create);
+ });
+ for (auto handle : sessions_to_ungap) {
+ HandleInfo& info = session_handles_[handle];
+ // Loading and re-saving allows the TPM to assign a new context counter.
+ std::string old_context_blob;
+ Serialize_TPMS_CONTEXT(info.context, &old_context_blob);
+ TPM_RC result = LoadContext(command_info, &info);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to un-gap session (load): "
+ << GetErrorString(result);
+ continue;
+ }
+ result = SaveContext(command_info, &info);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to un-gap session (save): "
+ << GetErrorString(result);
+ continue;
+ }
+ // If this context is one that we're tracking for external use, update it.
+ auto iter = actual_context_to_external_.find(old_context_blob);
+ if (iter == actual_context_to_external_.end()) {
+ continue;
+ }
+ std::string new_context_blob;
+ Serialize_TPMS_CONTEXT(info.context, &new_context_blob);
+ const std::string& external_context_blob = iter->second;
+ actual_context_to_external_[new_context_blob] = external_context_blob;
+ external_context_to_actual_[external_context_blob] = new_context_blob;
+ actual_context_to_external_.erase(old_context_blob);
+ }
+}
+
+bool ResourceManager::FixWarnings(const MessageInfo& command_info,
+ TPM_RC result) {
+ if ((result & RC_WARN) == 0) {
+ return false;
+ }
+ // This method can be called anytime without tracking whether the current
+ // operation is already an attempt to fix a warning. All re-entrance issues
+ // are dealt with here using the following rule: Never attempt to fix the same
+ // warning twice.
+ ScopedBool scoped_bool;
+ if (!fixing_warnings_) {
+ scoped_bool.Enable(&fixing_warnings_);
+ warnings_already_seen_.clear();
+ } else if (warnings_already_seen_.count(result) > 0) {
+ return false;
+ }
+ warnings_already_seen_.insert(result);
+ switch (result) {
+ case TPM_RC_CONTEXT_GAP:
+ FixContextGap(command_info);
+ return true;
+ case TPM_RC_OBJECT_MEMORY:
+ case TPM_RC_OBJECT_HANDLES:
+ EvictObjects(command_info);
+ return true;
+ case TPM_RC_SESSION_MEMORY:
+ EvictSession(command_info);
+ return true;
+ case TPM_RC_MEMORY:
+ EvictObjects(command_info);
+ EvictSession(command_info);
+ return true;
+ case TPM_RC_SESSION_HANDLES:
+ FlushSession(command_info);
+ return true;
+ }
+ return false;
+}
+
+void ResourceManager::FlushSession(const MessageInfo& command_info) {
+ TPM_HANDLE session_to_flush;
+ LOG(WARNING) << "Resource manager needs to flush a session.";
+ if (!ChooseSessionToEvict(command_info.session_handles, &session_to_flush)) {
+ return;
+ }
+ TPM_RC result = factory_.GetTpm()->FlushContextSync(session_to_flush,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Failed to flush session: " << GetErrorString(result);
+ return;
+ }
+ CleanupFlushedHandle(session_to_flush);
+}
+
+std::string ResourceManager::GetActualContextFromExternalContext(
+ const std::string& external_context) {
+ auto iter = external_context_to_actual_.find(external_context);
+ if (iter == external_context_to_actual_.end()) {
+ return external_context;
+ }
+ return iter->second;
+}
+
+bool ResourceManager::IsObjectHandle(TPM_HANDLE handle) const {
+ return ((handle & HR_RANGE_MASK) == HR_TRANSIENT);
+}
+
+bool ResourceManager::IsSessionHandle(TPM_HANDLE handle) const {
+ return ((handle & HR_RANGE_MASK) == HR_HMAC_SESSION ||
+ (handle & HR_RANGE_MASK) == HR_POLICY_SESSION);
+}
+
+TPM_RC ResourceManager::LoadContext(const MessageInfo& command_info,
+ HandleInfo* handle_info) {
+ CHECK(!handle_info->is_loaded);
+ TPM_RC result = TPM_RC_SUCCESS;
+ int attempts = 0;
+ while (attempts++ < kMaxCommandAttempts) {
+ result = factory_.GetTpm()->ContextLoadSync(handle_info->context,
+ &handle_info->tpm_handle,
+ nullptr);
+ if (!FixWarnings(command_info, result)) {
+ break;
+ }
+ }
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": Failed to load context: "
+ << GetErrorString(result);
+ return result;
+ }
+ handle_info->is_loaded = true;
+ return result;
+}
+
+TPM_RC ResourceManager::MakeError(TPM_RC tpm_error,
+ const ::tracked_objects::Location& location) {
+ LOG(ERROR) << "ResourceManager::" << location.function_name() << ":"
+ << location.line_number() << ": " << GetErrorString(tpm_error);
+ return tpm_error + kResourceManagerTpmErrorBase;
+}
+
+TPM_RC ResourceManager::ParseCommand(const std::string& command,
+ MessageInfo* command_info) {
+ CHECK(command_info);
+ std::string buffer = command;
+ TPM_ST tag;
+ TPM_RC result = Parse_TPM_ST(&buffer, &tag, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (tag != TPM_ST_SESSIONS && tag != TPM_ST_NO_SESSIONS) {
+ return MakeError(TPM_RC_TAG, FROM_HERE);
+ }
+ command_info->has_sessions = (tag == TPM_ST_SESSIONS);
+
+ UINT32 size = 0;
+ result = Parse_UINT32(&buffer, &size, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (size != command.size()) {
+ return MakeError(TPM_RC_SIZE, FROM_HERE);
+ }
+
+ result = Parse_TPM_CC(&buffer, &command_info->code, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (command_info->code < TPM_CC_FIRST || command_info->code > TPM_CC_LAST) {
+ return MakeError(TPM_RC_COMMAND_CODE, FROM_HERE);
+ }
+
+ size_t number_of_handles = GetNumberOfRequestHandles(command_info->code);
+ command_info->handles = ExtractHandlesFromBuffer(number_of_handles, &buffer);
+ if (number_of_handles != command_info->handles.size()) {
+ return MakeError(TPM_RC_SIZE, FROM_HERE);
+ }
+ if (command_info->has_sessions) {
+ // Sessions exist, so we're expecting a valid authorization size value.
+ UINT32 authorization_size = 0;
+ result = Parse_UINT32(&buffer, &authorization_size, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (buffer.size() < authorization_size ||
+ authorization_size < kMinimumAuthorizationSize) {
+ return MakeError(TPM_RC_SIZE, FROM_HERE);
+ }
+ // Move out the parameter bytes, leaving only the authorization section.
+ command_info->parameter_data = buffer.substr(authorization_size);
+ buffer.erase(authorization_size);
+ // Parse as many authorization sessions as there are in the section.
+ while (!buffer.empty()) {
+ TPM_HANDLE handle;
+ result = Parse_TPM_HANDLE(&buffer, &handle, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (handle != TPM_RS_PW && session_handles_.count(handle) == 0) {
+ return MakeError(TPM_RC_HANDLE, FROM_HERE);
+ }
+ TPM2B_NONCE nonce;
+ result = Parse_TPM2B_NONCE(&buffer, &nonce, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ BYTE attributes;
+ result = Parse_BYTE(&buffer, &attributes, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ TPM2B_DIGEST authorization;
+ result = Parse_TPM2B_DIGEST(&buffer, &authorization, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ command_info->session_handles.push_back(handle);
+ command_info->session_continued.push_back((attributes & 1) == 1);
+ }
+ } else {
+ // No sessions, so all remaining data is parameter data.
+ command_info->parameter_data = buffer;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC ResourceManager::ParseResponse(const MessageInfo& command_info,
+ const std::string& response,
+ MessageInfo* response_info) {
+ CHECK(response_info);
+ std::string buffer = response;
+ TPM_ST tag;
+ TPM_RC result = Parse_TPM_ST(&buffer, &tag, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (tag != TPM_ST_SESSIONS && tag != TPM_ST_NO_SESSIONS) {
+ return MakeError(TPM_RC_TAG, FROM_HERE);
+ }
+ response_info->has_sessions = (tag == TPM_ST_SESSIONS);
+
+ UINT32 size = 0;
+ result = Parse_UINT32(&buffer, &size, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (size != response.size()) {
+ return MakeError(TPM_RC_SIZE, FROM_HERE);
+ }
+
+ result = Parse_TPM_RC(&buffer, &response_info->code, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+
+ size_t number_of_handles = GetNumberOfResponseHandles(command_info.code);
+ response_info->handles = ExtractHandlesFromBuffer(number_of_handles, &buffer);
+ if (number_of_handles != response_info->handles.size()) {
+ return MakeError(TPM_RC_SIZE, FROM_HERE);
+ }
+ if (response_info->has_sessions) {
+ // Sessions exist, so we're expecting a valid parameter size value.
+ UINT32 parameter_size = 0;
+ result = Parse_UINT32(&buffer, &parameter_size, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ if (buffer.size() < parameter_size) {
+ return MakeError(TPM_RC_SIZE, FROM_HERE);
+ }
+ // Move out the parameter bytes, leaving only the authorization section.
+ response_info->parameter_data = buffer.substr(0, parameter_size);
+ buffer.erase(0, parameter_size);
+ // Parse as many authorization sessions as there are in the section.
+ while (!buffer.empty()) {
+ TPM2B_NONCE nonce;
+ result = Parse_TPM2B_NONCE(&buffer, &nonce, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ BYTE attributes;
+ result = Parse_BYTE(&buffer, &attributes, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ TPM2B_DIGEST acknowledgement;
+ result = Parse_TPM2B_DIGEST(&buffer, &acknowledgement, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ return MakeError(result, FROM_HERE);
+ }
+ response_info->session_continued.push_back((attributes & 1) == 1);
+ }
+ } else {
+ // No sessions, so all remaining data is parameter data.
+ response_info->parameter_data = buffer;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ResourceManager::ProcessExternalContextSave(
+ const MessageInfo& command_info,
+ const MessageInfo& response_info) {
+ CHECK_EQ(command_info.code, TPM_CC_ContextSave);
+ if (command_info.handles.size() != 1) {
+ LOG(WARNING) << "Invalid context save command.";
+ return;
+ }
+ // We know command_info.handles[0] is valid because this is validated when the
+ // command is parsed.
+ TPM_HANDLE saved_handle = command_info.handles[0];
+ // Only track external context data for session handles.
+ if (!IsSessionHandle(saved_handle)) {
+ return;
+ }
+ std::string mutable_parameter = response_info.parameter_data;
+ TPMS_CONTEXT context;
+ std::string context_blob;
+ TPM_RC result = Parse_TPMS_CONTEXT(&mutable_parameter,
+ &context,
+ &context_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Invalid context save response: " << GetErrorString(result);
+ return;
+ }
+ auto iter = session_handles_.find(saved_handle);
+ if (iter != session_handles_.end()) {
+ iter->second.is_loaded = false;
+ iter->second.context = context;
+ } else {
+ // Unknown handle? Not anymore.
+ LOG(WARNING) << "Context for unknown handle.";
+ HandleInfo new_handle_info;
+ new_handle_info.Init(saved_handle);
+ new_handle_info.is_loaded = false;
+ new_handle_info.context = context;
+ session_handles_[saved_handle] = new_handle_info;
+ }
+ // Use the original context data as the 'external' context data. If this gets
+ // virtualized, only the 'actual' context data will change.
+ external_context_to_actual_[context_blob] = context_blob;
+ actual_context_to_external_[context_blob] = context_blob;
+}
+
+std::string ResourceManager::ProcessFlushContext(
+ const std::string& command,
+ const MessageInfo& command_info) {
+ std::string buffer = command_info.parameter_data;
+ // There must be exactly one handle in the parameters section.
+ std::vector<TPM_HANDLE> handles = ExtractHandlesFromBuffer(1, &buffer);
+ if (handles.size() != 1) {
+ return CreateErrorResponse(MakeError(TPM_RC_SIZE, FROM_HERE));
+ }
+ TPM_HANDLE handle = handles[0];
+ TPM_HANDLE actual_handle = handle;
+ if (IsObjectHandle(handle)) {
+ auto iter = virtual_object_handles_.find(handle);
+ if (iter == virtual_object_handles_.end()) {
+ return CreateErrorResponse(MakeError(TPM_RC_HANDLE, FROM_HERE));
+ }
+ if (!iter->second.is_loaded) {
+ // The handle wasn't loaded so no need to bother the TPM.
+ CleanupFlushedHandle(handle);
+ return CreateErrorResponse(TPM_RC_SUCCESS);
+ }
+ actual_handle = iter->second.tpm_handle;
+ }
+ // Send a command with the original header but with |actual_handle| as the
+ // parameter.
+ std::string handle_blob;
+ Serialize_TPM_HANDLE(actual_handle, &handle_blob);
+ std::string updated_command = command.substr(0, kMessageHeaderSize) +
+ handle_blob;
+ // No need to loop and fix warnings, there are no actionable warnings on when
+ // flushing context.
+ std::string response = next_transceiver_->SendCommandAndWait(updated_command);
+ MessageInfo response_info;
+ TPM_RC result = ParseResponse(command_info, response, &response_info);
+ if (result != TPM_RC_SUCCESS) {
+ return CreateErrorResponse(result);
+ }
+ // Cleanup the handle locally even if the TPM did not recognize it.
+ if (response_info.code == TPM_RC_SUCCESS ||
+ response_info.code == TPM_RC_HANDLE) {
+ CleanupFlushedHandle(handle);
+ }
+ return response;
+}
+
+TPM_RC ResourceManager::ProcessInputHandle(const MessageInfo& command_info,
+ TPM_HANDLE virtual_handle,
+ TPM_HANDLE* actual_handle) {
+ // Only transient object handles are virtualized.
+ if (!IsObjectHandle(virtual_handle)) {
+ *actual_handle = virtual_handle;
+ return TPM_RC_SUCCESS;
+ }
+ auto handle_iter = virtual_object_handles_.find(virtual_handle);
+ if (handle_iter == virtual_object_handles_.end()) {
+ return MakeError(TPM_RC_HANDLE, FROM_HERE);
+ }
+ HandleInfo& handle_info = handle_iter->second;
+ if (!handle_info.is_loaded) {
+ TPM_RC result = LoadContext(command_info, &handle_info);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ tpm_object_handles_[handle_info.tpm_handle] = virtual_handle;
+ VLOG(1) << "RELOAD_OBJECT: " << std::hex << virtual_handle;
+ }
+ VLOG(1) << "INPUT_HANDLE_REPLACE: " << std::hex << virtual_handle << " -> "
+ << std::hex << handle_info.tpm_handle;
+ *actual_handle = handle_info.tpm_handle;
+ return TPM_RC_SUCCESS;
+}
+
+TPM_HANDLE ResourceManager::ProcessOutputHandle(TPM_HANDLE handle) {
+ // Track, but do not virtualize, session handles.
+ if (IsSessionHandle(handle)) {
+ auto session_handle_iter = session_handles_.find(handle);
+ if (session_handle_iter == session_handles_.end()) {
+ HandleInfo new_handle_info;
+ new_handle_info.Init(handle);
+ session_handles_[handle] = new_handle_info;
+ VLOG(1) << "OUTPUT_HANDLE_NEW_SESSION: " << std::hex << handle;
+ }
+ return handle;
+ }
+ // Only transient object handles are virtualized.
+ if (!IsObjectHandle(handle)) {
+ return handle;
+ }
+ auto virtual_handle_iter = tpm_object_handles_.find(handle);
+ if (virtual_handle_iter == tpm_object_handles_.end()) {
+ TPM_HANDLE new_virtual_handle = CreateVirtualHandle();
+ HandleInfo new_handle_info;
+ new_handle_info.Init(handle);
+ virtual_object_handles_[new_virtual_handle] = new_handle_info;
+ tpm_object_handles_[handle] = new_virtual_handle;
+ VLOG(1) << "OUTPUT_HANDLE_NEW_VIRTUAL: " << std::hex << handle << " -> "
+ << std::hex << new_virtual_handle;
+ return new_virtual_handle;
+ }
+ VLOG(1) << "OUTPUT_HANDLE_REPLACE: " << std::hex << handle << " -> "
+ << std::hex << virtual_handle_iter->second;
+ return virtual_handle_iter->second;
+}
+
+std::string ResourceManager::ReplaceHandles(
+ const std::string& message,
+ const std::vector<TPM_HANDLE>& new_handles) {
+ std::string handles_blob;
+ for (auto handle : new_handles) {
+ CHECK_EQ(Serialize_TPM_HANDLE(handle, &handles_blob), TPM_RC_SUCCESS);
+ }
+ std::string mutable_message = message;
+ CHECK_GE(message.size(), kMessageHeaderSize + handles_blob.size());
+ return mutable_message.replace(kMessageHeaderSize, handles_blob.size(),
+ handles_blob);
+}
+
+TPM_RC ResourceManager::SaveContext(const MessageInfo& command_info,
+ HandleInfo* handle_info) {
+ CHECK(handle_info->is_loaded);
+ TPM_RC result = TPM_RC_SUCCESS;
+ int attempts = 0;
+ while (attempts++ < kMaxCommandAttempts) {
+ std::string tpm_handle_name;
+ Serialize_TPM_HANDLE(handle_info->tpm_handle, &tpm_handle_name);
+ result = factory_.GetTpm()->ContextSaveSync(handle_info->tpm_handle,
+ tpm_handle_name,
+ &handle_info->context,
+ nullptr);
+ if (!FixWarnings(command_info, result)) {
+ break;
+ }
+ }
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": Failed to load context: "
+ << GetErrorString(result);
+ return result;
+ }
+ handle_info->is_loaded = false;
+ return result;
+}
+
+
+ResourceManager::HandleInfo::HandleInfo()
+ : is_loaded(false),
+ tpm_handle(0) {
+ memset(&context, 0, sizeof(TPMS_CONTEXT));
+}
+
+void ResourceManager::HandleInfo::Init(TPM_HANDLE handle) {
+ tpm_handle = handle;
+ is_loaded = true;
+ time_of_create = base::TimeTicks::Now();
+ time_of_last_use = base::TimeTicks::Now();
+}
+
+} // namespace trunks
diff --git a/trunks/resource_manager.h b/trunks/resource_manager.h
new file mode 100644
index 0000000..6bf4e82
--- /dev/null
+++ b/trunks/resource_manager.h
@@ -0,0 +1,238 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_RESOURCE_MANAGER_H_
+#define TRUNKS_RESOURCE_MANAGER_H_
+
+#include "trunks/command_transceiver.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <base/location.h>
+#include <base/macros.h>
+#include <base/time/time.h>
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+// The ResourceManager class manages access to limited TPM resources.
+//
+// It is reactive to and synchronous with active TPM commands, it does not
+// perform any background processing. It needs to inspect every TPM command and
+// reply. It maintains all actual TPM handles and provides its own handles to
+// callers. If a command fails because a resource is not available the resource
+// manager will perform the necessary evictions and run the command again. If a
+// command needs an object that has been evicted, that object will be loaded
+// before the command is sent to the TPM.
+//
+// In terms of interface the ResourceManager is simply a CommandTranceiver but
+// with the limitation that all calls are synchronous. The SendCommand method
+// is supported but does not return until the callback has been called. Keeping
+// ResourceManager synchronous simplifies the code and improves readability.
+// This class works well with a BackgroundCommandTransceiver.
+class ResourceManager : public CommandTransceiver {
+ public:
+ // The given |factory| will be used to create objects so mocks can be easily
+ // injected. This class retains a reference to the factory; the factory must
+ // remain valid for the duration of the ResourceManager lifetime. The
+ // |next_transceiver| will be used to forward commands to the TPM, this class
+ // does NOT take ownership of the pointer.
+ ResourceManager(const TrunksFactory& factory,
+ CommandTransceiver* next_transceiver);
+ ~ResourceManager() override;
+
+ void Initialize();
+
+ // CommandTransceiver methods.
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) override;
+
+ std::string SendCommandAndWait(const std::string& command) override;
+
+ private:
+ struct MessageInfo {
+ bool has_sessions;
+ TPM_CC code; // For a response message this is the TPM_RC response code.
+ std::vector<TPM_HANDLE> handles;
+ std::vector<TPM_HANDLE> session_handles;
+ std::vector<bool> session_continued;
+ std::string parameter_data;
+ };
+
+ struct HandleInfo {
+ HandleInfo();
+ // Initializes info for a loaded handle.
+ void Init(TPM_HANDLE handle);
+
+ bool is_loaded;
+ // Valid only if |is_loaded| is true.
+ TPM_HANDLE tpm_handle;
+ // Valid only if |is_loaded| is false.
+ TPMS_CONTEXT context;
+ // Time when the handle is create.
+ base::TimeTicks time_of_create;
+ // Time when the handle was last used.
+ base::TimeTicks time_of_last_use;
+ };
+
+ // Chooses an appropriate session for eviction (or flush) which is not one of
+ // |sessions_to_retain| and assigns it to |session_to_evict|. Returns true on
+ // success.
+ bool ChooseSessionToEvict(const std::vector<TPM_HANDLE>& sessions_to_retain,
+ TPM_HANDLE* session_to_evict);
+
+ // Cleans up all references to and information about |flushed_handle|.
+ void CleanupFlushedHandle(TPM_HANDLE flushed_handle);
+
+ // Creates a new virtual object handle. If the handle space is exhausted a
+ // valid handle is flushed and re-used.
+ TPM_HANDLE CreateVirtualHandle();
+
+ // Given a session handle, ensures the session is loaded in the TPM.
+ TPM_RC EnsureSessionIsLoaded(const MessageInfo& command_info,
+ TPM_HANDLE session_handle);
+
+ // Evicts all loaded objects except those required by |command_info|. The
+ // eviction is best effort; any errors will be ignored.
+ void EvictObjects(const MessageInfo& command_info);
+
+ // Evicts a session other than those required by |command_info|. The eviction
+ // is best effort; any errors will be ignored.
+ void EvictSession(const MessageInfo& command_info);
+
+ // Returns a list of handles parsed from a given |buffer|. No more than
+ // |number_of_handles| will be parsed.
+ std::vector<TPM_HANDLE> ExtractHandlesFromBuffer(size_t number_of_handles,
+ std::string* buffer);
+
+ // A context gap may occur when context counters for active sessions drift too
+ // far apart for the TPM to manage. Basically, the TPM needs to reassign new
+ // counters to saved sessions. See the TPM Library Specification Part 1
+ // Section 30.5 Session Context Management for details.
+ void FixContextGap(const MessageInfo& command_info);
+
+ // Performs best-effort handling of actionable warnings. The |command_info|
+ // must correspond with the current command being processed by the resource
+ // manager. Returns true only if |result| represents an actionable warning and
+ // it has been handled.
+ bool FixWarnings(const MessageInfo& command_info, TPM_RC result);
+
+ // Flushes a session other than those required by |command_info|. The flush is
+ // best effort; any errors will be ignored.
+ void FlushSession(const MessageInfo& command_info);
+
+ // When a caller saves context, the resource manager retains that context and
+ // possible trades it for new context data to fix a context gap (see
+ // FixContextGap). So when the caller wants to load the original context again
+ // it needs to be swapped with the latest actual context maintained by the
+ // resource manager. This method finds the correct TPM context for a given
+ // |external_context| previously returned to the caller. If not found,
+ // |external_context| is returned.
+ std::string GetActualContextFromExternalContext(
+ const std::string& external_context);
+
+ // Returns true iff |handle| is a transient object handle.
+ bool IsObjectHandle(TPM_HANDLE handle) const;
+
+ // Returns true iff |handle| is a session handle.
+ bool IsSessionHandle(TPM_HANDLE handle) const;
+
+ // Loads the context for a session or object handle. On success returns
+ // TPM_RC_SUCCESS and ensures |handle_info| holds a valid handle (and invalid
+ // context data).
+ TPM_RC LoadContext(const MessageInfo& command_info, HandleInfo* handle_info);
+
+ // Returns a resource manager error code given a particular |tpm_error| and
+ // logs the occurrence of the error.
+ TPM_RC MakeError(TPM_RC tpm_error,
+ const ::tracked_objects::Location& location);
+
+ // Parses a |command|, sanity checking its format and extracting
+ // |message_info| on success. Returns TPM_RC_SUCCESS on success.
+ TPM_RC ParseCommand(const std::string& command, MessageInfo* message_info);
+
+ // Parses a |response| to a command associated with |command_info|. The
+ // response is sanity checked and |response_info| is extracted. Returns
+ // TPM_RC_SUCCESS on success.
+ TPM_RC ParseResponse(const MessageInfo& command_info,
+ const std::string& response,
+ MessageInfo* response_info);
+
+ // Performs processing after a successful external ContextSave operation.
+ // A subsequent call to GetActualContextFromExternalContext will succeed for
+ // the context.
+ void ProcessExternalContextSave(const MessageInfo& command_info,
+ const MessageInfo& response_info);
+
+ // Process an external flush context |command|.
+ std::string ProcessFlushContext(const std::string& command,
+ const MessageInfo& command_info);
+
+ // Given a |virtual_handle| created by this resource manager, finds the
+ // associated TPM |actual_handle|, restoring the object if necessary. The
+ // current |command_info| must be provided. If |virtual_handle| is not an
+ // object handle, then |actual_handle| is set to |virtual_handle|. Returns
+ // TPM_RC_SUCCESS on success.
+ TPM_RC ProcessInputHandle(const MessageInfo& command_info,
+ TPM_HANDLE virtual_handle,
+ TPM_HANDLE* actual_handle);
+
+ // Given a TPM object handle, returns an associated virtual handle, generating
+ // a new one if necessary.
+ TPM_HANDLE ProcessOutputHandle(TPM_HANDLE object_handle);
+
+ // Replaces all handles in a given |message| with |new_handles| and returns
+ // the resulting modified message. The modified message is guaranteed to have
+ // the same length as the input message.
+ std::string ReplaceHandles(const std::string& message,
+ const std::vector<TPM_HANDLE>& new_handles);
+
+ // Saves the context for a session or object handle. On success returns
+ // TPM_RC_SUCCESS and ensures |handle_info| holds valid context data.
+ TPM_RC SaveContext(const MessageInfo& command_info, HandleInfo* handle_info);
+
+ const TrunksFactory& factory_;
+ CommandTransceiver* next_transceiver_ = nullptr;
+ TPM_HANDLE next_virtual_handle_ = TRANSIENT_FIRST;
+
+ // A mapping of known virtual handles to corresponding HandleInfo.
+ std::map<TPM_HANDLE, HandleInfo> virtual_object_handles_;
+ // A mapping of loaded tpm object handles to the corresponding virtual handle.
+ std::map<TPM_HANDLE, TPM_HANDLE> tpm_object_handles_;
+ // A mapping of known session handles to corresponding HandleInfo.
+ std::map<TPM_HANDLE, HandleInfo> session_handles_;
+ // A mapping of external context blobs to current context blobs.
+ std::map<std::string, std::string> external_context_to_actual_;
+ // A mapping of actual context blobs to external context blobs.
+ std::map<std::string, std::string> actual_context_to_external_;
+
+ // The set of warnings already handled in the context of a FixWarnings() call.
+ // Tracking this allows us to avoid re-entrance.
+ std::set<TPM_RC> warnings_already_seen_;
+ // Whether a FixWarnings() call is currently executing.
+ bool fixing_warnings_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceManager);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_RESOURCE_MANAGER_H_
diff --git a/trunks/resource_manager_test.cc b/trunks/resource_manager_test.cc
new file mode 100644
index 0000000..5d2f43e
--- /dev/null
+++ b/trunks/resource_manager_test.cc
@@ -0,0 +1,894 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/resource_manager.h"
+
+#include <string>
+#include <vector>
+
+#include <base/bind.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/mock_command_transceiver.h"
+#include "trunks/mock_tpm.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Eq;
+using testing::Field;
+using testing::InSequence;
+using testing::Return;
+using testing::ReturnPointee;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace {
+
+const trunks::TPM_HANDLE kArbitraryObjectHandle = trunks::TRANSIENT_FIRST + 25;
+const trunks::TPM_HANDLE kArbitrarySessionHandle = trunks::HMAC_SESSION_FIRST;
+
+void Assign(std::string* to, const std::string& from) {
+ *to = from;
+}
+
+class ScopedDisableLogging {
+ public:
+ ScopedDisableLogging() : original_severity_(logging::GetMinLogLevel()) {
+ logging::SetMinLogLevel(logging::LOG_FATAL);
+ }
+ ~ScopedDisableLogging() {
+ logging::SetMinLogLevel(original_severity_);
+ }
+
+ private:
+ logging::LogSeverity original_severity_;
+};
+
+} // namespace
+
+namespace trunks {
+
+class ResourceManagerTest : public testing::Test {
+ public:
+ const std::vector<TPM_HANDLE> kNoHandles;
+ const std::string kNoAuthorization;
+ const std::string kNoParameters;
+
+ ResourceManagerTest() : resource_manager_(factory_, &transceiver_) {}
+ ~ResourceManagerTest() override {}
+
+ void SetUp() override {
+ factory_.set_tpm(&tpm_);
+ }
+
+ // Builds a well-formed command.
+ std::string CreateCommand(TPM_CC code,
+ const std::vector<TPM_HANDLE>& handles,
+ const std::string& authorization,
+ const std::string& parameters) {
+ std::string buffer;
+ TPM_ST tag = authorization.empty() ? TPM_ST_NO_SESSIONS : TPM_ST_SESSIONS;
+ UINT32 size = 10 + (handles.size() * 4) + authorization.size() +
+ parameters.size() + (authorization.empty() ? 0 : 4);
+ Serialize_TPM_ST(tag, &buffer);
+ Serialize_UINT32(size, &buffer);
+ Serialize_TPM_CC(code, &buffer);
+ for (auto handle : handles) {
+ Serialize_TPM_HANDLE(handle, &buffer);
+ }
+ if (!authorization.empty()) {
+ Serialize_UINT32(authorization.size(), &buffer);
+ }
+ return buffer + authorization + parameters;
+ }
+
+ // Builds a well-formed response.
+ std::string CreateResponse(TPM_RC code,
+ const std::vector<TPM_HANDLE>& handles,
+ const std::string& authorization,
+ const std::string& parameters) {
+ std::string buffer;
+ TPM_ST tag = authorization.empty() ? TPM_ST_NO_SESSIONS : TPM_ST_SESSIONS;
+ UINT32 size = 10 + (handles.size() * 4) + authorization.size() +
+ parameters.size() + (authorization.empty() ? 0 : 4);
+ Serialize_TPM_ST(tag, &buffer);
+ Serialize_UINT32(size, &buffer);
+ Serialize_TPM_RC(code, &buffer);
+ for (auto handle : handles) {
+ Serialize_TPM_HANDLE(handle, &buffer);
+ }
+ if (!authorization.empty()) {
+ Serialize_UINT32(parameters.size(), &buffer);
+ }
+ return buffer + parameters + authorization;
+ }
+
+ // Builds a well-formed command authorization section.
+ std::string CreateCommandAuthorization(TPM_HANDLE handle,
+ bool continue_session) {
+ std::string buffer;
+ Serialize_TPM_HANDLE(handle, &buffer);
+ Serialize_TPM2B_NONCE(Make_TPM2B_DIGEST(std::string(32, 'A')), &buffer);
+ Serialize_BYTE(continue_session ? 1 : 0, &buffer);
+ Serialize_TPM2B_DIGEST(Make_TPM2B_DIGEST(std::string(32, 'B')), &buffer);
+ return buffer;
+ }
+
+ // Builds a well-formed response authorization section.
+ std::string CreateResponseAuthorization(bool continue_session) {
+ std::string buffer;
+ Serialize_TPM2B_NONCE(Make_TPM2B_DIGEST(std::string(32, 'A')), &buffer);
+ Serialize_BYTE(continue_session ? 1 : 0, &buffer);
+ Serialize_TPM2B_DIGEST(Make_TPM2B_DIGEST(std::string(32, 'B')), &buffer);
+ return buffer;
+ }
+
+ std::string GetHeader(const std::string& message) {
+ return message.substr(0, 10);
+ }
+
+ std::string StripHeader(const std::string& message) {
+ return message.substr(10);
+ }
+
+ // Makes the resource manager aware of a transient object handle and returns
+ // the newly associated virtual handle.
+ TPM_HANDLE LoadHandle(TPM_HANDLE handle) {
+ std::vector<TPM_HANDLE> input_handles = {PERSISTENT_FIRST};
+ std::string command = CreateCommand(TPM_CC_Load,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::vector<TPM_HANDLE> output_handles = {handle};
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ output_handles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ std::string handle_blob = StripHeader(actual_response);
+ TPM_HANDLE virtual_handle;
+ CHECK_EQ(TPM_RC_SUCCESS, Parse_TPM_HANDLE(&handle_blob, &virtual_handle,
+ NULL));
+ return virtual_handle;
+ }
+
+ // Causes the resource manager to evict existing object handles.
+ void EvictObjects() {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateErrorResponse(TPM_RC_OBJECT_MEMORY);
+ std::string success_response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillOnce(Return(response))
+ .WillRepeatedly(Return(success_response));
+ EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(tpm_, FlushContextSync(_, _))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ resource_manager_.SendCommandAndWait(command);
+ }
+
+ // Makes the resource manager aware of a session handle.
+ void StartSession(TPM_HANDLE handle) {
+ std::vector<TPM_HANDLE> input_handles = {1, 2};
+ std::string command = CreateCommand(TPM_CC_StartAuthSession,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::vector<TPM_HANDLE> output_handles = {handle};
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ output_handles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ ASSERT_EQ(response, actual_response);
+ }
+
+ // Causes the resource manager to evict an existing session handle.
+ void EvictSession() {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateErrorResponse(TPM_RC_SESSION_MEMORY);
+ std::string success_response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillOnce(Return(response))
+ .WillRepeatedly(Return(success_response));
+ EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ resource_manager_.SendCommandAndWait(command);
+ }
+
+ // Creates a TPMS_CONTEXT with the given sequence field.
+ TPMS_CONTEXT CreateContext(UINT64 sequence) {
+ TPMS_CONTEXT context = {sequence};
+ return context;
+ }
+
+ // Creates a serialized TPMS_CONTEXT with the given sequence field.
+ std::string CreateContextParameter(UINT64 sequence) {
+ std::string buffer;
+ Serialize_TPMS_CONTEXT(CreateContext(sequence), &buffer);
+ return buffer;
+ }
+
+ protected:
+ StrictMock<MockTpm> tpm_;
+ TrunksFactoryForTest factory_;
+ StrictMock<MockCommandTransceiver> transceiver_;
+ ResourceManager resource_manager_;
+};
+
+TEST_F(ResourceManagerTest, BasicPassThrough) {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(actual_response, response);
+}
+
+TEST_F(ResourceManagerTest, BasicPassThroughAsync) {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response;
+ CommandTransceiver::ResponseCallback callback =
+ base::Bind(&Assign, &actual_response);
+ resource_manager_.SendCommand(command, callback);
+ EXPECT_EQ(actual_response, response);
+}
+
+TEST_F(ResourceManagerTest, VirtualHandleOutput) {
+ std::vector<TPM_HANDLE> input_handles = {PERSISTENT_FIRST};
+ std::string command = CreateCommand(TPM_CC_Load,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::vector<TPM_HANDLE> output_handles = {kArbitraryObjectHandle};
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ output_handles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response.size(), actual_response.size());
+ // We expect the resource manager has replaced the output handle with a
+ // virtual handle (which we can't predict, but it's unlikely to be the same as
+ // the handle emitted by the mock).
+ EXPECT_EQ(GetHeader(response), GetHeader(actual_response));
+ EXPECT_NE(StripHeader(response), StripHeader(actual_response));
+ TPM_HT handle_type = static_cast<TPM_HT>(StripHeader(actual_response)[0]);
+ EXPECT_EQ(TPM_HT_TRANSIENT, handle_type);
+}
+
+TEST_F(ResourceManagerTest, VirtualHandleInput) {
+ TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
+ TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
+ std::vector<TPM_HANDLE> input_handles = {virtual_handle};
+ std::string command = CreateCommand(TPM_CC_Sign,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ // We expect the resource manager to replace |virtual_handle| with
+ // |tpm_handle|.
+ std::vector<TPM_HANDLE> expected_input_handles = {tpm_handle};
+ std::string expected_command = CreateCommand(TPM_CC_Sign,
+ expected_input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(expected_command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, VirtualHandleCleanup) {
+ TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
+ TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
+ std::string parameters;
+ Serialize_TPM_HANDLE(virtual_handle, &parameters);
+ std::string command = CreateCommand(TPM_CC_FlushContext,
+ kNoHandles,
+ kNoAuthorization,
+ parameters);
+ std::string expected_parameters;
+ Serialize_TPM_HANDLE(tpm_handle, &expected_parameters);
+ std::string expected_command = CreateCommand(TPM_CC_FlushContext,
+ kNoHandles,
+ kNoAuthorization,
+ expected_parameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(expected_command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+ // Now we expect there to be no record of |virtual_handle|.
+ std::vector<TPM_HANDLE> input_handles = {virtual_handle};
+ command = CreateCommand(TPM_CC_Sign,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ response = CreateErrorResponse(TPM_RC_HANDLE | kResourceManagerTpmErrorBase);
+ actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+
+ // Try again but attempt to flush |tpm_handle| instead of |virtual_handle|.
+ virtual_handle = LoadHandle(tpm_handle);
+ parameters.clear();
+ Serialize_TPM_HANDLE(tpm_handle, &parameters);
+ command = CreateCommand(TPM_CC_FlushContext,
+ kNoHandles,
+ kNoAuthorization,
+ parameters);
+ actual_response = resource_manager_.SendCommandAndWait(command);
+ // TPM_RC_HANDLE also expected here.
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, VirtualHandleLoadBeforeUse) {
+ TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
+ TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
+ EvictObjects();
+ std::vector<TPM_HANDLE> input_handles = {virtual_handle};
+ std::string command = CreateCommand(TPM_CC_Sign,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::vector<TPM_HANDLE> expected_input_handles = {tpm_handle};
+ std::string expected_command = CreateCommand(TPM_CC_Sign,
+ expected_input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(transceiver_, SendCommandAndWait(expected_command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, InvalidVirtualHandle) {
+ std::vector<TPM_HANDLE> input_handles = {kArbitraryObjectHandle};
+ std::string command = CreateCommand(TPM_CC_Sign,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateErrorResponse(TPM_RC_HANDLE |
+ kResourceManagerTpmErrorBase);
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, SimpleFuzzInputParser) {
+ std::vector<TPM_HANDLE> handles = {1, 2};
+ std::string parameters = "12345";
+ std::string command = CreateCommand(TPM_CC_StartAuthSession,
+ handles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ true), // continue_session
+ parameters);
+ // We don't care about what happens, only that it doesn't crash.
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(CreateErrorResponse(TPM_RC_FAILURE)));
+ ScopedDisableLogging no_logging;
+ for (size_t i = 0; i < command.size(); ++i) {
+ resource_manager_.SendCommandAndWait(command.substr(0, i));
+ resource_manager_.SendCommandAndWait(command.substr(i));
+ std::string fuzzed_command(command);
+ for (uint8_t value = 0; ; value++) {
+ fuzzed_command[i] = static_cast<char>(value);
+ resource_manager_.SendCommandAndWait(fuzzed_command);
+ if (value == 255) {
+ break;
+ }
+ }
+ }
+}
+
+TEST_F(ResourceManagerTest, SimpleFuzzOutputParser) {
+ std::vector<TPM_HANDLE> handles = {1, 2};
+ std::string parameters = "12345";
+ std::string command = CreateCommand(TPM_CC_StartAuthSession,
+ handles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ true), // continue_session
+ parameters);
+ std::vector<TPM_HANDLE> out_handles = {3};
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ out_handles,
+ CreateResponseAuthorization(
+ true), // continue_session
+ parameters);
+ std::string fuzzed_response;
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(ReturnPointee(&fuzzed_response));
+ ScopedDisableLogging no_logging;
+ for (size_t i = 0; i < response.size(); ++i) {
+ fuzzed_response = response.substr(0, i);
+ resource_manager_.SendCommandAndWait(command);
+ fuzzed_response = response.substr(i);
+ resource_manager_.SendCommandAndWait(command);
+ fuzzed_response = response;
+ for (uint8_t value = 0; ; value++) {
+ fuzzed_response[i] = static_cast<char>(value);
+ resource_manager_.SendCommandAndWait(command);
+ if (value == 255) {
+ break;
+ }
+ }
+ fuzzed_response[i] = response[i];
+ }
+}
+
+TEST_F(ResourceManagerTest, NewSession) {
+ StartSession(kArbitrarySessionHandle);
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ true), // continue_session
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ CreateResponseAuthorization(
+ true), // continue_session
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, DiscontinuedSession) {
+ StartSession(kArbitrarySessionHandle);
+ // Use the session but do not continue.
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ false), // continue_session
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ CreateResponseAuthorization(
+ false), // continue_session
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+ // Now attempt to use it again and expect a handle error.
+ response = CreateErrorResponse(TPM_RC_HANDLE | kResourceManagerTpmErrorBase);
+ actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, LoadSessionBeforeUse) {
+ StartSession(kArbitrarySessionHandle);
+ EvictSession();
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ true), // continue_session
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ CreateResponseAuthorization(
+ true), // continue_session
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, SessionHandleCleanup) {
+ StartSession(kArbitrarySessionHandle);
+ std::string parameters;
+ Serialize_TPM_HANDLE(kArbitrarySessionHandle, &parameters);
+ std::string command = CreateCommand(TPM_CC_FlushContext,
+ kNoHandles,
+ kNoAuthorization,
+ parameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+ // Now we expect there to be no record of |kArbitrarySessionHandle|.
+ command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ true), // continue_session
+ kNoParameters);
+ response = CreateErrorResponse(TPM_RC_HANDLE | kResourceManagerTpmErrorBase);
+ actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, EvictWhenObjectInUse) {
+ TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
+ TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
+ TPM_HANDLE tpm_handle2 = kArbitraryObjectHandle + 1;
+ LoadHandle(tpm_handle2);
+ std::vector<TPM_HANDLE> input_handles = {virtual_handle};
+ std::string command = CreateCommand(TPM_CC_Sign,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ // Trigger evict logic and verify |input_handles| are not evicted.
+ std::string response = CreateErrorResponse(TPM_RC_OBJECT_MEMORY);
+ std::string success_response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(tpm_, ContextSaveSync(tpm_handle2, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(tpm_, FlushContextSync(tpm_handle2, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillOnce(Return(response))
+ .WillRepeatedly(Return(success_response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(success_response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, EvictWhenSessionInUse) {
+ StartSession(kArbitrarySessionHandle);
+ StartSession(kArbitrarySessionHandle + 1);
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle,
+ true), // continue_session
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ CreateResponseAuthorization(
+ true), // continue_session
+ kNoParameters);
+ std::string error_response = CreateErrorResponse(TPM_RC_SESSION_MEMORY);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillOnce(Return(error_response))
+ .WillRepeatedly(Return(response));
+ EXPECT_CALL(tpm_, ContextSaveSync(kArbitrarySessionHandle + 1, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, EvictMultipleObjects) {
+ const int kNumObjects = 10;
+ std::map<TPM_HANDLE, TPM_HANDLE> handles;
+ for (int i = 0; i < kNumObjects; ++i) {
+ TPM_HANDLE handle = kArbitraryObjectHandle + i;
+ handles[LoadHandle(handle)] = handle;
+ }
+ EvictObjects();
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .Times(kNumObjects)
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(response));
+ for (auto item : handles) {
+ std::vector<TPM_HANDLE> input_handles = {item.first};
+ std::string command = CreateCommand(TPM_CC_Sign,
+ input_handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+ }
+}
+
+TEST_F(ResourceManagerTest, EvictMostStaleSession) {
+ StartSession(kArbitrarySessionHandle);
+ StartSession(kArbitrarySessionHandle + 1);
+ StartSession(kArbitrarySessionHandle + 2);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ CreateResponseAuthorization(
+ true), // continue_session
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(response));
+ // Use the first two sessions, leaving the third as the most stale.
+ for (int i = 0; i < 2; ++i) {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle + i,
+ true), // continue_session
+ kNoParameters);
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+ }
+ EvictSession();
+ // EvictSession will have messed with the expectations; set them again.
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(response));
+ // Use the first two sessions again, expecting no calls to ContextLoad.
+ for (int i = 0; i < 2; ++i) {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle + i,
+ true), // continue_session
+ kNoParameters);
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+ }
+ // Expect a call to ContextLoad if we use the third session.
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ kArbitrarySessionHandle + 2,
+ true), // continue_session
+ kNoParameters);
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, HandleContextGap) {
+ const int kNumSessions = 7;
+ const int kNumSessionsToUngap = 4;
+ std::vector<TPM_HANDLE> expected_ungap_order;
+ for (int i = 0; i < kNumSessions; ++i) {
+ StartSession(kArbitrarySessionHandle + i);
+ if (i < kNumSessionsToUngap) {
+ EvictSession();
+ expected_ungap_order.push_back(kArbitrarySessionHandle + i);
+ }
+ }
+ // Invoke a context gap.
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateErrorResponse(TPM_RC_CONTEXT_GAP);
+ std::string success_response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ {
+ InSequence ungap_order;
+ for (auto handle : expected_ungap_order) {
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(tpm_, ContextSaveSync(handle, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ }
+ }
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillOnce(Return(response))
+ .WillRepeatedly(Return(success_response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(success_response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, ExternalContext) {
+ StartSession(kArbitrarySessionHandle);
+ // Do an external context save.
+ std::vector<TPM_HANDLE> handles = {kArbitrarySessionHandle};
+ std::string context_save = CreateCommand(TPM_CC_ContextSave,
+ handles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string context_parameter1 = CreateContextParameter(1);
+ std::string context_save_response1 = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ context_parameter1);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(context_save))
+ .WillOnce(Return(context_save_response1));
+ std::string actual_response = resource_manager_.SendCommandAndWait(
+ context_save);
+ EXPECT_EQ(context_save_response1, actual_response);
+
+ // Invoke a context gap (which will cause context1 to be mapped to context2).
+ EXPECT_CALL(tpm_, ContextLoadSync(Field(&TPMS_CONTEXT::sequence, Eq(1)),
+ _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(tpm_, ContextSaveSync(kArbitrarySessionHandle, _, _, _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(CreateContext(2)),
+ Return(TPM_RC_SUCCESS)));
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = CreateErrorResponse(TPM_RC_CONTEXT_GAP);
+ std::string success_response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response))
+ .WillOnce(Return(success_response));
+ actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(success_response, actual_response);
+
+ // Now load external context1 and expect an actual load of context2.
+ std::string context_load1 = CreateCommand(TPM_CC_ContextLoad,
+ kNoHandles,
+ kNoAuthorization,
+ context_parameter1);
+ std::string context_load2 = CreateCommand(TPM_CC_ContextLoad,
+ kNoHandles,
+ kNoAuthorization,
+ CreateContextParameter(2));
+ std::string context_load_response = CreateResponse(TPM_RC_SUCCESS,
+ handles,
+ kNoAuthorization,
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(context_load2))
+ .WillOnce(Return(context_load_response));
+ actual_response = resource_manager_.SendCommandAndWait(context_load1);
+ EXPECT_EQ(context_load_response, actual_response);
+}
+
+TEST_F(ResourceManagerTest, NestedFailures) {
+ // The scenario being tested is when a command results in a warning to be
+ // handled by the resource manager, and in the process of handling the first
+ // warning another warning occurs which should be handled by the resource
+ // manager, etc..
+ for (int i = 0; i < 3; ++i) {
+ LoadHandle(kArbitraryObjectHandle + i);
+ }
+ EvictObjects();
+ for (int i = 3; i < 6; ++i) {
+ LoadHandle(kArbitraryObjectHandle + i);
+ }
+ for (int i = 0; i < 10; ++i) {
+ StartSession(kArbitrarySessionHandle + i);
+ EvictSession();
+ }
+ for (int i = 10; i < 20; ++i) {
+ StartSession(kArbitrarySessionHandle + i);
+ }
+ std::string error_response = CreateErrorResponse(TPM_RC_MEMORY);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(error_response));
+ // The TPM_RC_MEMORY will result in a context save, make that fail too.
+ EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_CONTEXT_GAP));
+ // The TPM_RC_CONTEXT_GAP will result in a context load.
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .WillRepeatedly(Return(TPM_RC_SESSION_HANDLES));
+ // The TPM_RC_SESSION_HANDLES will result in a context flush.
+ EXPECT_CALL(tpm_, FlushContextSync(_, _))
+ .WillRepeatedly(Return(TPM_RC_SESSION_MEMORY));
+ // The resource manager should not handle the same warning twice so we expect
+ // the error of the original call to bubble up.
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(error_response, response);
+}
+
+TEST_F(ResourceManagerTest, OutOfMemory) {
+ std::string error_response = CreateErrorResponse(TPM_RC_MEMORY);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(error_response));
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(error_response, response);
+}
+
+TEST_F(ResourceManagerTest, ReentrantFixGap) {
+ for (int i = 0; i < 3; ++i) {
+ StartSession(kArbitrarySessionHandle + i);
+ EvictSession();
+ }
+ for (int i = 3; i < 6; ++i) {
+ StartSession(kArbitrarySessionHandle + i);
+ }
+ std::string error_response = CreateErrorResponse(TPM_RC_CONTEXT_GAP);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(_))
+ .WillRepeatedly(Return(error_response));
+ EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_CONTEXT_GAP));
+ EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
+ .WillOnce(Return(TPM_RC_CONTEXT_GAP))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ kNoAuthorization,
+ kNoParameters);
+ std::string response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(error_response, response);
+}
+
+TEST_F(ResourceManagerTest, PasswordAuthorization) {
+ std::string command = CreateCommand(TPM_CC_Startup,
+ kNoHandles,
+ CreateCommandAuthorization(
+ TPM_RS_PW,
+ false), // continue_session
+ kNoParameters);
+ std::string response = CreateResponse(TPM_RC_SUCCESS,
+ kNoHandles,
+ CreateResponseAuthorization(
+ false), // continue_session
+ kNoParameters);
+ EXPECT_CALL(transceiver_, SendCommandAndWait(command))
+ .WillOnce(Return(response));
+ std::string actual_response = resource_manager_.SendCommandAndWait(command);
+ EXPECT_EQ(response, actual_response);
+}
+
+} // namespace trunks
diff --git a/trunks/scoped_key_handle.cc b/trunks/scoped_key_handle.cc
new file mode 100644
index 0000000..e8b4800
--- /dev/null
+++ b/trunks/scoped_key_handle.cc
@@ -0,0 +1,81 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/scoped_key_handle.h"
+
+#include <base/logging.h>
+
+#include "trunks/error_codes.h"
+
+namespace {
+
+const trunks::TPM_HANDLE kInvalidHandle = 0;
+
+} // namespace
+
+namespace trunks {
+
+ScopedKeyHandle::ScopedKeyHandle(const TrunksFactory& factory)
+ : factory_(factory),
+ handle_(kInvalidHandle) {}
+
+ScopedKeyHandle::ScopedKeyHandle(const TrunksFactory& factory,
+ TPM_HANDLE handle)
+ : factory_(factory),
+ handle_(handle) {}
+
+ScopedKeyHandle::~ScopedKeyHandle() {
+ if (handle_ != kInvalidHandle) {
+ FlushHandleContext(handle_);
+ }
+}
+
+TPM_HANDLE ScopedKeyHandle::release() {
+ TPM_HANDLE tmp_handle = handle_;
+ handle_ = kInvalidHandle;
+ return tmp_handle;
+}
+
+void ScopedKeyHandle::reset(TPM_HANDLE new_handle) {
+ TPM_HANDLE tmp_handle = handle_;
+ handle_ = new_handle;
+ if (tmp_handle != kInvalidHandle) {
+ FlushHandleContext(tmp_handle);
+ }
+}
+
+void ScopedKeyHandle::reset() {
+ reset(kInvalidHandle);
+}
+
+TPM_HANDLE* ScopedKeyHandle::ptr() {
+ return &handle_;
+}
+
+TPM_HANDLE ScopedKeyHandle::get() const {
+ return handle_;
+}
+
+void ScopedKeyHandle::FlushHandleContext(TPM_HANDLE handle) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ result = factory_.GetTpm()->FlushContextSync(handle, nullptr);
+ if (result) {
+ LOG(WARNING) << "Error closing handle: " << handle << " : "
+ << GetErrorString(result);
+ }
+}
+
+} // namespace trunks
diff --git a/trunks/scoped_key_handle.h b/trunks/scoped_key_handle.h
new file mode 100644
index 0000000..ddd38cc
--- /dev/null
+++ b/trunks/scoped_key_handle.h
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_SCOPED_KEY_HANDLE_H_
+#define TRUNKS_SCOPED_KEY_HANDLE_H_
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+// This class is used to wrap a Key or NV ram handle given by the TPM.
+// It provides a destructor that cleans up TPM resources associated with
+// that handle.
+class TRUNKS_EXPORT ScopedKeyHandle {
+ public:
+ // We provide a factory to the constructor so that we can later free
+ // resources associated with the handle.
+ explicit ScopedKeyHandle(const TrunksFactory& factory);
+ ScopedKeyHandle(const TrunksFactory& factory, TPM_HANDLE handle);
+ virtual ~ScopedKeyHandle();
+
+ // This method releases the TPM_HANDLE associated with this class.
+ // It returns the handle that was previously wrapped, and returns
+ // INVALID_HANDLE if the previous handle was unset.
+ virtual TPM_HANDLE release();
+
+ // This method flushes all context associated with the current handle,
+ // and has the class wrap |new_handle|
+ virtual void reset(TPM_HANDLE new_handle);
+
+ // This method flushes all context associated with the current handle,
+ // and resets the internal handle of the class to the uninitialized value.
+ // Note: After reset() this class should not be used again till a new handle
+ // is injected.
+ virtual void reset();
+
+ // This method returns a pointer to the handle associated with this class.
+ // This method does not transfer ownership.
+ virtual TPM_HANDLE* ptr();
+
+ // This method returns the handle currectly associated with the class.
+ // This method does not transfer ownership, therefore the handle returned
+ // might be stale.
+ virtual TPM_HANDLE get() const;
+
+ private:
+ const TrunksFactory& factory_;
+ TPM_HANDLE handle_;
+ void FlushHandleContext(TPM_HANDLE handle);
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedKeyHandle);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_SCOPED_KEY_HANDLE_H_
diff --git a/trunks/scoped_key_handle_test.cc b/trunks/scoped_key_handle_test.cc
new file mode 100644
index 0000000..2d91917
--- /dev/null
+++ b/trunks/scoped_key_handle_test.cc
@@ -0,0 +1,94 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/scoped_key_handle.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/mock_tpm.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::WithArgs;
+
+namespace trunks {
+
+// A test fixture for TpmState tests.
+class ScopedKeyHandleTest : public testing::Test {
+ public:
+ ScopedKeyHandleTest() {}
+ ~ScopedKeyHandleTest() override {}
+
+ void SetUp() override {
+ factory_.set_tpm(&mock_tpm_);
+ }
+
+ protected:
+ TrunksFactoryForTest factory_;
+ NiceMock<MockTpm> mock_tpm_;
+};
+
+TEST_F(ScopedKeyHandleTest, FlushHandle) {
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ ScopedKeyHandle scoped_handle(factory_, handle);
+ EXPECT_CALL(mock_tpm_, FlushContextSync(handle, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+}
+
+TEST_F(ScopedKeyHandleTest, GetTest) {
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ ScopedKeyHandle scoped_handle(factory_, handle);
+ EXPECT_EQ(handle, scoped_handle.get());
+}
+
+TEST_F(ScopedKeyHandleTest, ReleaseTest) {
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ ScopedKeyHandle scoped_handle(factory_, handle);
+ EXPECT_EQ(handle, scoped_handle.release());
+ EXPECT_EQ(0, scoped_handle.get());
+}
+
+TEST_F(ScopedKeyHandleTest, ResetAndFlush) {
+ TPM_HANDLE old_handle = TPM_RH_FIRST;
+ TPM_HANDLE new_handle = TPM_RH_NULL;
+ ScopedKeyHandle scoped_handle(factory_, old_handle);
+ EXPECT_EQ(old_handle, scoped_handle.get());
+ EXPECT_CALL(mock_tpm_, FlushContextSync(old_handle, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ scoped_handle.reset(new_handle);
+ EXPECT_EQ(new_handle, scoped_handle.get());
+ EXPECT_CALL(mock_tpm_, FlushContextSync(new_handle, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+}
+
+TEST_F(ScopedKeyHandleTest, NullReset) {
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ ScopedKeyHandle scoped_handle(factory_, handle);
+ EXPECT_EQ(handle, scoped_handle.get());
+ EXPECT_CALL(mock_tpm_, FlushContextSync(handle, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ scoped_handle.reset();
+ EXPECT_EQ(0, scoped_handle.get());
+}
+
+} // namespace trunks
diff --git a/trunks/session_manager.h b/trunks/session_manager.h
new file mode 100644
index 0000000..3e0a14d
--- /dev/null
+++ b/trunks/session_manager.h
@@ -0,0 +1,73 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_SESSION_MANAGER_H_
+#define TRUNKS_SESSION_MANAGER_H_
+
+#include <string>
+
+#include "trunks/hmac_authorization_delegate.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+const trunks::TPM_HANDLE kUninitializedHandle = 0;
+
+// This class is used to keep track of a TPM session. Each instance of this
+// class is used to account for one instance of a TPM session. Currently
+// this class is used by AuthorizationSession instances to keep track of TPM
+// sessions.
+// Note: This class is not intended to be used independently. However clients
+// who want to manually manage their sessions can use this class to Start and
+// Close TPM backed Sessions. Example usage:
+// trunks::TrunksFactoryImpl factory;
+// scoped_ptr<SessionManager> session_manager = factory.GetSessionManager();
+// session_manager->StartSession(...);
+// TPM_HANDLE session_handle = session_manager->GetSessionHandle();
+class TRUNKS_EXPORT SessionManager {
+ public:
+ SessionManager() {}
+ virtual ~SessionManager() {}
+
+ // This method is used get the handle to the AuthorizationSession managed by
+ // this instance.
+ virtual TPM_HANDLE GetSessionHandle() const = 0;
+
+ // This method is used to flush all TPM context associated with the current
+ // session
+ virtual void CloseSession() = 0;
+
+ // This method is used to start a new AuthorizationSession. Once started,
+ // GetSessionHandle() can be used to access the handle to the TPM session.
+ // Since the sessions are salted, we need to ensure that TPM ownership is
+ // taken and the salting key created before this method is called.
+ // Returns TPM_RC_SUCCESS and returns the nonces used to create the session
+ // on success.
+ virtual TPM_RC StartSession(TPM_SE session_type,
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption,
+ HmacAuthorizationDelegate* delegate) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SessionManager);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_SESSION_MANAGER_H_
diff --git a/trunks/session_manager_impl.cc b/trunks/session_manager_impl.cc
new file mode 100644
index 0000000..b71c4ee
--- /dev/null
+++ b/trunks/session_manager_impl.cc
@@ -0,0 +1,210 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/session_manager_impl.h"
+
+#include <string>
+
+#include <base/logging.h>
+#include <base/stl_util.h>
+#include <crypto/scoped_openssl_types.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/tpm_utility.h"
+
+namespace {
+const size_t kWellKnownExponent = 0x10001;
+} // namespace
+
+namespace trunks {
+
+SessionManagerImpl::SessionManagerImpl(const TrunksFactory& factory)
+ : factory_(factory),
+ session_handle_(kUninitializedHandle) {}
+
+SessionManagerImpl::~SessionManagerImpl() {
+ CloseSession();
+}
+
+void SessionManagerImpl::CloseSession() {
+ if (session_handle_ == kUninitializedHandle) {
+ return;
+ }
+ TPM_RC result = factory_.GetTpm()->FlushContextSync(session_handle_, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(WARNING) << "Error closing tpm session: " << GetErrorString(result);
+ }
+ session_handle_ = kUninitializedHandle;
+}
+
+TPM_RC SessionManagerImpl::StartSession(
+ TPM_SE session_type,
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption,
+ HmacAuthorizationDelegate* delegate) {
+ CHECK(delegate);
+ // If we already have an active session, close it.
+ CloseSession();
+
+ std::string salt(SHA256_DIGEST_SIZE, 0);
+ unsigned char* salt_buffer =
+ reinterpret_cast<unsigned char*>(string_as_array(&salt));
+ CHECK_EQ(RAND_bytes(salt_buffer, salt.size()), 1)
+ << "Error generating a cryptographically random salt.";
+ // First we enccrypt the cryptographically secure salt using PKCS1_OAEP
+ // padded RSA public key encryption. This is specified in TPM2.0
+ // Part1 Architecture, Appendix B.10.2.
+ std::string encrypted_salt;
+ TPM_RC salt_result = EncryptSalt(salt, &encrypted_salt);
+ if (salt_result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error encrypting salt.";
+ return salt_result;
+ }
+
+ TPM2B_ENCRYPTED_SECRET encrypted_secret =
+ Make_TPM2B_ENCRYPTED_SECRET(encrypted_salt);
+ // Then we use TPM2_StartAuthSession to start a HMAC session with the TPM.
+ // The tpm returns the tpm_nonce and the session_handle referencing the
+ // created session.
+ TPMI_ALG_HASH hash_algorithm = TPM_ALG_SHA256;
+ TPMT_SYM_DEF symmetric_algorithm;
+ symmetric_algorithm.algorithm = TPM_ALG_AES;
+ symmetric_algorithm.key_bits.aes = 128;
+ symmetric_algorithm.mode.aes = TPM_ALG_CFB;
+
+ TPM2B_NONCE nonce_caller;
+ TPM2B_NONCE nonce_tpm;
+ // We use sha1_digest_size here because that is the minimum length
+ // needed for the nonce.
+ nonce_caller.size = SHA1_DIGEST_SIZE;
+ CHECK_EQ(RAND_bytes(nonce_caller.buffer, nonce_caller.size), 1)
+ << "Error generating a cryptographically random nonce.";
+
+ Tpm* tpm = factory_.GetTpm();
+ // The TPM2 command below needs no authorization. This is why we can use
+ // the empty string "", when referring to the handle names for the salting
+ // key and the bind entity.
+ TPM_RC tpm_result = tpm->StartAuthSessionSync(kSaltingKey,
+ "", // salt_handle_name.
+ bind_entity,
+ "", // bind_entity_name.
+ nonce_caller,
+ encrypted_secret,
+ session_type,
+ symmetric_algorithm,
+ hash_algorithm,
+ &session_handle_,
+ &nonce_tpm,
+ nullptr); // No Authorization.
+ if (tpm_result) {
+ LOG(ERROR) << "Error creating an authorization session: "
+ << GetErrorString(tpm_result);
+ return tpm_result;
+ }
+ bool hmac_result = delegate->InitSession(
+ session_handle_,
+ nonce_tpm,
+ nonce_caller,
+ salt,
+ bind_authorization_value,
+ enable_encryption);
+ if (!hmac_result) {
+ LOG(ERROR) << "Failed to initialize an authorization session delegate.";
+ return TPM_RC_FAILURE;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC SessionManagerImpl::EncryptSalt(const std::string& salt,
+ std::string* encrypted_salt) {
+ TPM2B_NAME out_name;
+ TPM2B_NAME qualified_name;
+ TPM2B_PUBLIC public_data;
+ public_data.public_area.unique.rsa.size = 0;
+ // The TPM2 Command below needs no authorization. Therefore we can simply
+ // use the empty string for all the Key names, and pullptr for the
+ // authorization delegate.
+ TPM_RC result = factory_.GetTpm()->ReadPublicSync(
+ kSaltingKey, "", // SaltingKey name.
+ &public_data, &out_name, &qualified_name, nullptr); // No authorization
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error fetching salting key public info.";
+ return result;
+ }
+ crypto::ScopedRSA salting_rsa(RSA_new());
+ salting_rsa.get()->e = BN_new();
+ if (!salting_rsa.get()->e) {
+ LOG(ERROR) << "Error creating exponent for RSA.";
+ return TPM_RC_FAILURE;
+ }
+ BN_set_word(salting_rsa.get()->e, kWellKnownExponent);
+ salting_rsa.get()->n = BN_bin2bn(public_data.public_area.unique.rsa.buffer,
+ public_data.public_area.unique.rsa.size,
+ nullptr);
+ if (!salting_rsa.get()->n) {
+ LOG(ERROR) << "Error setting public area of rsa key.";
+ return TPM_RC_FAILURE;
+ }
+ // Label for RSAES-OAEP. Defined in TPM2.0 Part1 Architecture,
+ // Appendix B.10.2.
+ unsigned char oaep_param[7] = {'S', 'E', 'C', 'R', 'E', 'T', '\0'};
+ const EVP_MD* sha256_md = EVP_sha256();
+ std::string padded_input(RSA_size(salting_rsa.get()), 0);
+ int rsa_result = RSA_padding_add_PKCS1_OAEP_mgf1(
+ reinterpret_cast<unsigned char*>(string_as_array(&padded_input)),
+ padded_input.size(),
+ reinterpret_cast<const unsigned char*>(salt.c_str()),
+ salt.size(),
+ oaep_param,
+ arraysize(oaep_param),
+ sha256_md,
+ sha256_md);
+ if (!rsa_result) {
+ unsigned long err = ERR_get_error(); // NOLINT openssl types
+ ERR_load_ERR_strings();
+ ERR_load_crypto_strings();
+ LOG(ERROR) << "EncryptSalt Error: " << err
+ << ": " << ERR_lib_error_string(err)
+ << ", " << ERR_func_error_string(err)
+ << ", " << ERR_reason_error_string(err);
+ return TPM_RC_FAILURE;
+ }
+ encrypted_salt->resize(padded_input.size());
+ rsa_result = RSA_public_encrypt(
+ padded_input.size(),
+ reinterpret_cast<unsigned char*>(string_as_array(&padded_input)),
+ reinterpret_cast<unsigned char*>(string_as_array(encrypted_salt)),
+ salting_rsa.get(),
+ RSA_NO_PADDING);
+ if (rsa_result == -1) {
+ unsigned long err = ERR_get_error(); // NOLINT openssl types
+ ERR_load_ERR_strings();
+ ERR_load_crypto_strings();
+ LOG(ERROR) << "EncryptSalt Error: " << err
+ << ": " << ERR_lib_error_string(err)
+ << ", " << ERR_func_error_string(err)
+ << ", " << ERR_reason_error_string(err);
+ return TPM_RC_FAILURE;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+} // namespace trunks
diff --git a/trunks/session_manager_impl.h b/trunks/session_manager_impl.h
new file mode 100644
index 0000000..967bde6
--- /dev/null
+++ b/trunks/session_manager_impl.h
@@ -0,0 +1,72 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_SESSION_MANAGER_IMPL_H_
+#define TRUNKS_SESSION_MANAGER_IMPL_H_
+
+#include "trunks/session_manager.h"
+
+#include <string>
+
+#include <gtest/gtest_prod.h>
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+// This class is used to keep track of a TPM session. Each instance of this
+// class is used to account for one instance of a TPM session. Currently
+// this class is used by AuthorizationSession instances to keep track of TPM
+// sessions.
+class TRUNKS_EXPORT SessionManagerImpl : public SessionManager {
+ public:
+ explicit SessionManagerImpl(const TrunksFactory& factory);
+ ~SessionManagerImpl() override;
+
+ TPM_HANDLE GetSessionHandle() const override { return session_handle_; }
+ void CloseSession() override;
+ TPM_RC StartSession(TPM_SE session_type,
+ TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption,
+ HmacAuthorizationDelegate* delegate) override;
+
+ private:
+ // This function is used to encrypt a plaintext salt |salt|, using RSA
+ // public encrypt with the SaltingKey PKCS1_OAEP padding. It follows the
+ // specification defined in TPM2.0 Part 1 Architecture, Appendix B.10.2.
+ // The encrypted salt is stored in the out parameter |encrypted_salt|.
+ TPM_RC EncryptSalt(const std::string& salt, std::string* encrypted_salt);
+
+ // This factory is only set in the constructor and is used to instantiate
+ // The TPM class to forward commands to the TPM chip.
+ const TrunksFactory& factory_;
+ // This handle keeps track of the TPM session. It is issued by the TPM,
+ // and is only modified when a new TPM session is started using
+ // StartBoundSession or StartUnboundSession. We use this to keep track of
+ // the session handle, so that we can clean it up when this class is
+ // destroyed.
+ TPM_HANDLE session_handle_;
+
+ friend class SessionManagerTest;
+ DISALLOW_COPY_AND_ASSIGN(SessionManagerImpl);
+};
+
+} // namespace trunks
+
+
+#endif // TRUNKS_SESSION_MANAGER_IMPL_H_
diff --git a/trunks/session_manager_test.cc b/trunks/session_manager_test.cc
new file mode 100644
index 0000000..4b38835
--- /dev/null
+++ b/trunks/session_manager_test.cc
@@ -0,0 +1,169 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/session_manager_impl.h"
+
+#include <vector>
+
+#include <base/strings/string_number_conversions.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/mock_tpm.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/tpm_utility.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgPointee;
+
+namespace trunks {
+
+class SessionManagerTest : public testing::Test {
+ public:
+ SessionManagerTest() : session_manager_(factory_) {
+ delegate_ = new HmacAuthorizationDelegate();
+ }
+ ~SessionManagerTest() override {}
+
+ void SetUp() override {
+ factory_.set_tpm(&mock_tpm_);
+ }
+
+ void SetHandle(TPM_HANDLE handle) {
+ session_manager_.session_handle_ = handle;
+ }
+
+ TPM2B_PUBLIC_KEY_RSA GetValidRSAPublicKey() {
+ const char kValidModulus[] =
+ "A1D50D088994000492B5F3ED8A9C5FC8772706219F4C063B2F6A8C6B74D3AD6B"
+ "212A53D01DABB34A6261288540D420D3BA59ED279D859DE6227A7AB6BD88FADD"
+ "FC3078D465F4DF97E03A52A587BD0165AE3B180FE7B255B7BEDC1BE81CB1383F"
+ "E9E46F9312B1EF28F4025E7D332E33F4416525FEB8F0FC7B815E8FBB79CDABE6"
+ "327B5A155FEF13F559A7086CB8A543D72AD6ECAEE2E704FF28824149D7F4E393"
+ "D3C74E721ACA97F7ADBE2CCF7B4BCC165F7380F48065F2C8370F25F066091259"
+ "D14EA362BAF236E3CD8771A94BDEDA3900577143A238AB92B6C55F11DEFAFB31"
+ "7D1DC5B6AE210C52B008D87F2A7BFF6EB5C4FB32D6ECEC6505796173951A3167";
+ std::vector<uint8> bytes;
+ CHECK(base::HexStringToBytes(kValidModulus, &bytes));
+ CHECK_EQ(bytes.size(), 256u);
+ TPM2B_PUBLIC_KEY_RSA rsa;
+ rsa.size = bytes.size();
+ memcpy(rsa.buffer, bytes.data(), bytes.size());
+ return rsa;
+ }
+
+ protected:
+ TrunksFactoryForTest factory_;
+ NiceMock<MockTpm> mock_tpm_;
+ HmacAuthorizationDelegate* delegate_;
+ SessionManagerImpl session_manager_;
+};
+
+TEST_F(SessionManagerTest, CloseSessionSuccess) {
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ SetHandle(handle);
+ EXPECT_CALL(mock_tpm_, FlushContextSync(handle, nullptr))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ session_manager_.CloseSession();
+}
+
+TEST_F(SessionManagerTest, CloseSessionNoHandle) {
+ TPM_HANDLE handle = kUninitializedHandle;
+ SetHandle(handle);
+ EXPECT_CALL(mock_tpm_, FlushContextSync(handle, nullptr))
+ .Times(0);
+ session_manager_.CloseSession();
+}
+
+TEST_F(SessionManagerTest, GetSessionHandleTest) {
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ EXPECT_EQ(kUninitializedHandle, session_manager_.GetSessionHandle());
+ SetHandle(handle);
+ EXPECT_EQ(handle, session_manager_.GetSessionHandle());
+}
+
+
+TEST_F(SessionManagerTest, StartSessionSuccess) {
+ TPM_SE session_type = TPM_SE_TRIAL;
+ TPM2B_PUBLIC public_data;
+ public_data.public_area.unique.rsa = GetValidRSAPublicKey();
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, nullptr))
+ .WillOnce(DoAll(SetArgPointee<2>(public_data),
+ Return(TPM_RC_SUCCESS)));
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ TPM2B_NONCE nonce;
+ nonce.size = 20;
+ EXPECT_CALL(mock_tpm_, StartAuthSessionSyncShort(_, handle,
+ _, _, session_type, _, _,
+ _, _, _))
+ .WillOnce(DoAll(SetArgPointee<8>(nonce),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, session_manager_.StartSession(session_type,
+ handle, "", false,
+ delegate_));
+}
+
+TEST_F(SessionManagerTest, StartSessionBadSaltingKey) {
+ TPM2B_PUBLIC public_data;
+ public_data.public_area.unique.rsa.size = 32;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, nullptr))
+ .WillOnce(DoAll(SetArgPointee<2>(public_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_FAILURE, session_manager_.StartSession(TPM_SE_TRIAL,
+ TPM_RH_NULL, "",
+ false, delegate_));
+}
+
+TEST_F(SessionManagerTest, StartSessionFailure) {
+ TPM2B_PUBLIC public_data;
+ public_data.public_area.unique.rsa = GetValidRSAPublicKey();
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, nullptr))
+ .WillOnce(DoAll(SetArgPointee<2>(public_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, StartAuthSessionSyncShort(_,
+ TPM_RH_NULL,
+ _, _, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, session_manager_.StartSession(TPM_SE_TRIAL,
+ TPM_RH_NULL, "",
+ false, delegate_));
+}
+
+TEST_F(SessionManagerTest, StartSessionBadNonce) {
+ TPM_SE session_type = TPM_SE_TRIAL;
+ TPM2B_PUBLIC public_data;
+ public_data.public_area.unique.rsa = GetValidRSAPublicKey();
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, nullptr))
+ .WillOnce(DoAll(SetArgPointee<2>(public_data),
+ Return(TPM_RC_SUCCESS)));
+ TPM_HANDLE handle = TPM_RH_FIRST;
+ TPM2B_NONCE nonce;
+ nonce.size = 0;
+ EXPECT_CALL(mock_tpm_, StartAuthSessionSyncShort(_, handle,
+ _, _, session_type, _, _,
+ _, _, _))
+ .WillOnce(DoAll(SetArgPointee<8>(nonce),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_FAILURE, session_manager_.StartSession(session_type,
+ handle, "", false,
+ delegate_));
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_constants.h b/trunks/tpm_constants.h
new file mode 100644
index 0000000..e06cc65
--- /dev/null
+++ b/trunks/tpm_constants.h
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_CONSTANTS_H_
+#define TRUNKS_TPM_CONSTANTS_H_
+
+#include "trunks/tpm_generated.h"
+
+namespace trunks {
+
+// TPM Object Attributes.
+const TPMA_OBJECT kFixedTPM = 1U << 1;
+const TPMA_OBJECT kFixedParent = 1U << 4;
+const TPMA_OBJECT kSensitiveDataOrigin = 1U << 5;
+const TPMA_OBJECT kUserWithAuth = 1U << 6;
+const TPMA_OBJECT kAdminWithPolicy = 1U << 7;
+const TPMA_OBJECT kNoDA = 1U << 10;
+const TPMA_OBJECT kRestricted = 1U << 16;
+const TPMA_OBJECT kDecrypt = 1U << 17;
+const TPMA_OBJECT kSign = 1U << 18;
+
+// TPM NV Index Attributes, defined in TPM Spec Part 2 section 13.2.
+const TPMA_NV TPMA_NV_OWNERWRITE = 1U << 1;
+const TPMA_NV TPMA_NV_WRITELOCKED = 1U << 11;
+const TPMA_NV TPMA_NV_WRITEDEFINE = 1U << 13;
+const TPMA_NV TPMA_NV_AUTHREAD = 1U << 18;
+const TPMA_NV TPMA_NV_NO_DA = 1U << 25;
+const TPMA_NV TPMA_NV_WRITTEN = 1U << 29;
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_CONSTANTS_H_
diff --git a/trunks/tpm_generated.cc b/trunks/tpm_generated.cc
new file mode 100644
index 0000000..657c880
--- /dev/null
+++ b/trunks/tpm_generated.cc
@@ -0,0 +1,41014 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+// THIS CODE IS GENERATED - DO NOT MODIFY!
+
+#include "trunks/tpm_generated.h"
+
+#include <string>
+
+#include <base/basictypes.h>
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/logging.h>
+#include <base/stl_util.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/sys_byteorder.h>
+#include <crypto/secure_hash.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/command_transceiver.h"
+#include "trunks/error_codes.h"
+
+
+namespace trunks {
+
+size_t GetNumberOfRequestHandles(TPM_CC command_code) {
+ switch (command_code) {
+ case TPM_CC_Startup: return 0;
+ case TPM_CC_Shutdown: return 0;
+ case TPM_CC_SelfTest: return 0;
+ case TPM_CC_IncrementalSelfTest: return 0;
+ case TPM_CC_GetTestResult: return 0;
+ case TPM_CC_StartAuthSession: return 2;
+ case TPM_CC_PolicyRestart: return 1;
+ case TPM_CC_Create: return 1;
+ case TPM_CC_Load: return 1;
+ case TPM_CC_LoadExternal: return 0;
+ case TPM_CC_ReadPublic: return 1;
+ case TPM_CC_ActivateCredential: return 2;
+ case TPM_CC_MakeCredential: return 1;
+ case TPM_CC_Unseal: return 1;
+ case TPM_CC_ObjectChangeAuth: return 2;
+ case TPM_CC_Duplicate: return 2;
+ case TPM_CC_Rewrap: return 2;
+ case TPM_CC_Import: return 1;
+ case TPM_CC_RSA_Encrypt: return 1;
+ case TPM_CC_RSA_Decrypt: return 1;
+ case TPM_CC_ECDH_KeyGen: return 1;
+ case TPM_CC_ECDH_ZGen: return 1;
+ case TPM_CC_ECC_Parameters: return 0;
+ case TPM_CC_ZGen_2Phase: return 1;
+ case TPM_CC_EncryptDecrypt: return 1;
+ case TPM_CC_Hash: return 0;
+ case TPM_CC_HMAC: return 1;
+ case TPM_CC_GetRandom: return 0;
+ case TPM_CC_StirRandom: return 0;
+ case TPM_CC_HMAC_Start: return 1;
+ case TPM_CC_HashSequenceStart: return 0;
+ case TPM_CC_SequenceUpdate: return 1;
+ case TPM_CC_SequenceComplete: return 1;
+ case TPM_CC_EventSequenceComplete: return 2;
+ case TPM_CC_Certify: return 2;
+ case TPM_CC_CertifyCreation: return 2;
+ case TPM_CC_Quote: return 1;
+ case TPM_CC_GetSessionAuditDigest: return 3;
+ case TPM_CC_GetCommandAuditDigest: return 2;
+ case TPM_CC_GetTime: return 2;
+ case TPM_CC_Commit: return 1;
+ case TPM_CC_EC_Ephemeral: return 0;
+ case TPM_CC_VerifySignature: return 1;
+ case TPM_CC_Sign: return 1;
+ case TPM_CC_SetCommandCodeAuditStatus: return 1;
+ case TPM_CC_PCR_Extend: return 1;
+ case TPM_CC_PCR_Event: return 1;
+ case TPM_CC_PCR_Read: return 0;
+ case TPM_CC_PCR_Allocate: return 1;
+ case TPM_CC_PCR_SetAuthPolicy: return 2;
+ case TPM_CC_PCR_SetAuthValue: return 1;
+ case TPM_CC_PCR_Reset: return 1;
+ case TPM_CC_PolicySigned: return 2;
+ case TPM_CC_PolicySecret: return 2;
+ case TPM_CC_PolicyTicket: return 1;
+ case TPM_CC_PolicyOR: return 1;
+ case TPM_CC_PolicyPCR: return 1;
+ case TPM_CC_PolicyLocality: return 1;
+ case TPM_CC_PolicyNV: return 3;
+ case TPM_CC_PolicyCounterTimer: return 1;
+ case TPM_CC_PolicyCommandCode: return 1;
+ case TPM_CC_PolicyPhysicalPresence: return 1;
+ case TPM_CC_PolicyCpHash: return 1;
+ case TPM_CC_PolicyNameHash: return 1;
+ case TPM_CC_PolicyDuplicationSelect: return 1;
+ case TPM_CC_PolicyAuthorize: return 1;
+ case TPM_CC_PolicyAuthValue: return 1;
+ case TPM_CC_PolicyPassword: return 1;
+ case TPM_CC_PolicyGetDigest: return 1;
+ case TPM_CC_PolicyNvWritten: return 1;
+ case TPM_CC_CreatePrimary: return 1;
+ case TPM_CC_HierarchyControl: return 1;
+ case TPM_CC_SetPrimaryPolicy: return 1;
+ case TPM_CC_ChangePPS: return 1;
+ case TPM_CC_ChangeEPS: return 1;
+ case TPM_CC_Clear: return 1;
+ case TPM_CC_ClearControl: return 1;
+ case TPM_CC_HierarchyChangeAuth: return 1;
+ case TPM_CC_DictionaryAttackLockReset: return 1;
+ case TPM_CC_DictionaryAttackParameters: return 1;
+ case TPM_CC_PP_Commands: return 1;
+ case TPM_CC_SetAlgorithmSet: return 1;
+ case TPM_CC_FieldUpgradeStart: return 2;
+ case TPM_CC_FieldUpgradeData: return 0;
+ case TPM_CC_FirmwareRead: return 0;
+ case TPM_CC_ContextSave: return 1;
+ case TPM_CC_ContextLoad: return 0;
+ case TPM_CC_FlushContext: return 0;
+ case TPM_CC_EvictControl: return 2;
+ case TPM_CC_ReadClock: return 0;
+ case TPM_CC_ClockSet: return 1;
+ case TPM_CC_ClockRateAdjust: return 1;
+ case TPM_CC_GetCapability: return 0;
+ case TPM_CC_TestParms: return 0;
+ case TPM_CC_NV_DefineSpace: return 1;
+ case TPM_CC_NV_UndefineSpace: return 2;
+ case TPM_CC_NV_UndefineSpaceSpecial: return 2;
+ case TPM_CC_NV_ReadPublic: return 1;
+ case TPM_CC_NV_Write: return 2;
+ case TPM_CC_NV_Increment: return 2;
+ case TPM_CC_NV_Extend: return 2;
+ case TPM_CC_NV_SetBits: return 2;
+ case TPM_CC_NV_WriteLock: return 2;
+ case TPM_CC_NV_GlobalWriteLock: return 1;
+ case TPM_CC_NV_Read: return 2;
+ case TPM_CC_NV_ReadLock: return 2;
+ case TPM_CC_NV_ChangeAuth: return 1;
+ case TPM_CC_NV_Certify: return 3;
+ default: LOG(WARNING) << "Unknown command code: " << command_code;
+ }
+ return 0;
+}
+
+size_t GetNumberOfResponseHandles(TPM_CC command_code) {
+ switch (command_code) {
+ case TPM_CC_Startup: return 0;
+ case TPM_CC_Shutdown: return 0;
+ case TPM_CC_SelfTest: return 0;
+ case TPM_CC_IncrementalSelfTest: return 0;
+ case TPM_CC_GetTestResult: return 0;
+ case TPM_CC_StartAuthSession: return 1;
+ case TPM_CC_PolicyRestart: return 0;
+ case TPM_CC_Create: return 0;
+ case TPM_CC_Load: return 1;
+ case TPM_CC_LoadExternal: return 1;
+ case TPM_CC_ReadPublic: return 0;
+ case TPM_CC_ActivateCredential: return 0;
+ case TPM_CC_MakeCredential: return 0;
+ case TPM_CC_Unseal: return 0;
+ case TPM_CC_ObjectChangeAuth: return 0;
+ case TPM_CC_Duplicate: return 0;
+ case TPM_CC_Rewrap: return 0;
+ case TPM_CC_Import: return 0;
+ case TPM_CC_RSA_Encrypt: return 0;
+ case TPM_CC_RSA_Decrypt: return 0;
+ case TPM_CC_ECDH_KeyGen: return 0;
+ case TPM_CC_ECDH_ZGen: return 0;
+ case TPM_CC_ECC_Parameters: return 0;
+ case TPM_CC_ZGen_2Phase: return 0;
+ case TPM_CC_EncryptDecrypt: return 0;
+ case TPM_CC_Hash: return 0;
+ case TPM_CC_HMAC: return 0;
+ case TPM_CC_GetRandom: return 0;
+ case TPM_CC_StirRandom: return 0;
+ case TPM_CC_HMAC_Start: return 1;
+ case TPM_CC_HashSequenceStart: return 1;
+ case TPM_CC_SequenceUpdate: return 0;
+ case TPM_CC_SequenceComplete: return 0;
+ case TPM_CC_EventSequenceComplete: return 0;
+ case TPM_CC_Certify: return 0;
+ case TPM_CC_CertifyCreation: return 0;
+ case TPM_CC_Quote: return 0;
+ case TPM_CC_GetSessionAuditDigest: return 0;
+ case TPM_CC_GetCommandAuditDigest: return 0;
+ case TPM_CC_GetTime: return 0;
+ case TPM_CC_Commit: return 0;
+ case TPM_CC_EC_Ephemeral: return 0;
+ case TPM_CC_VerifySignature: return 0;
+ case TPM_CC_Sign: return 0;
+ case TPM_CC_SetCommandCodeAuditStatus: return 0;
+ case TPM_CC_PCR_Extend: return 0;
+ case TPM_CC_PCR_Event: return 0;
+ case TPM_CC_PCR_Read: return 0;
+ case TPM_CC_PCR_Allocate: return 0;
+ case TPM_CC_PCR_SetAuthPolicy: return 0;
+ case TPM_CC_PCR_SetAuthValue: return 0;
+ case TPM_CC_PCR_Reset: return 0;
+ case TPM_CC_PolicySigned: return 0;
+ case TPM_CC_PolicySecret: return 0;
+ case TPM_CC_PolicyTicket: return 0;
+ case TPM_CC_PolicyOR: return 0;
+ case TPM_CC_PolicyPCR: return 0;
+ case TPM_CC_PolicyLocality: return 0;
+ case TPM_CC_PolicyNV: return 0;
+ case TPM_CC_PolicyCounterTimer: return 0;
+ case TPM_CC_PolicyCommandCode: return 0;
+ case TPM_CC_PolicyPhysicalPresence: return 0;
+ case TPM_CC_PolicyCpHash: return 0;
+ case TPM_CC_PolicyNameHash: return 0;
+ case TPM_CC_PolicyDuplicationSelect: return 0;
+ case TPM_CC_PolicyAuthorize: return 0;
+ case TPM_CC_PolicyAuthValue: return 0;
+ case TPM_CC_PolicyPassword: return 0;
+ case TPM_CC_PolicyGetDigest: return 0;
+ case TPM_CC_PolicyNvWritten: return 0;
+ case TPM_CC_CreatePrimary: return 1;
+ case TPM_CC_HierarchyControl: return 0;
+ case TPM_CC_SetPrimaryPolicy: return 0;
+ case TPM_CC_ChangePPS: return 0;
+ case TPM_CC_ChangeEPS: return 0;
+ case TPM_CC_Clear: return 0;
+ case TPM_CC_ClearControl: return 0;
+ case TPM_CC_HierarchyChangeAuth: return 0;
+ case TPM_CC_DictionaryAttackLockReset: return 0;
+ case TPM_CC_DictionaryAttackParameters: return 0;
+ case TPM_CC_PP_Commands: return 0;
+ case TPM_CC_SetAlgorithmSet: return 0;
+ case TPM_CC_FieldUpgradeStart: return 0;
+ case TPM_CC_FieldUpgradeData: return 0;
+ case TPM_CC_FirmwareRead: return 0;
+ case TPM_CC_ContextSave: return 0;
+ case TPM_CC_ContextLoad: return 1;
+ case TPM_CC_FlushContext: return 0;
+ case TPM_CC_EvictControl: return 0;
+ case TPM_CC_ReadClock: return 0;
+ case TPM_CC_ClockSet: return 0;
+ case TPM_CC_ClockRateAdjust: return 0;
+ case TPM_CC_GetCapability: return 0;
+ case TPM_CC_TestParms: return 0;
+ case TPM_CC_NV_DefineSpace: return 0;
+ case TPM_CC_NV_UndefineSpace: return 0;
+ case TPM_CC_NV_UndefineSpaceSpecial: return 0;
+ case TPM_CC_NV_ReadPublic: return 0;
+ case TPM_CC_NV_Write: return 0;
+ case TPM_CC_NV_Increment: return 0;
+ case TPM_CC_NV_Extend: return 0;
+ case TPM_CC_NV_SetBits: return 0;
+ case TPM_CC_NV_WriteLock: return 0;
+ case TPM_CC_NV_GlobalWriteLock: return 0;
+ case TPM_CC_NV_Read: return 0;
+ case TPM_CC_NV_ReadLock: return 0;
+ case TPM_CC_NV_ChangeAuth: return 0;
+ case TPM_CC_NV_Certify: return 0;
+ default: LOG(WARNING) << "Unknown command code: " << command_code;
+ }
+ return 0;
+}
+
+TPM_RC Serialize_uint8_t(const uint8_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ uint8_t value_net = value;
+ switch (sizeof(uint8_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(uint8_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_uint8_t(
+ std::string* buffer,
+ uint8_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(uint8_t))
+ return TPM_RC_INSUFFICIENT;
+ uint8_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(uint8_t));
+ switch (sizeof(uint8_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(uint8_t)));
+ }
+ buffer->erase(0, sizeof(uint8_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_int8_t(const int8_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ int8_t value_net = value;
+ switch (sizeof(int8_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(int8_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_int8_t(
+ std::string* buffer,
+ int8_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(int8_t))
+ return TPM_RC_INSUFFICIENT;
+ int8_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(int8_t));
+ switch (sizeof(int8_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(int8_t)));
+ }
+ buffer->erase(0, sizeof(int8_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_int(const int& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ int value_net = value;
+ switch (sizeof(int)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(int));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_int(
+ std::string* buffer,
+ int* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(int))
+ return TPM_RC_INSUFFICIENT;
+ int value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(int));
+ switch (sizeof(int)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(int)));
+ }
+ buffer->erase(0, sizeof(int));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_uint16_t(const uint16_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ uint16_t value_net = value;
+ switch (sizeof(uint16_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(uint16_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_uint16_t(
+ std::string* buffer,
+ uint16_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(uint16_t))
+ return TPM_RC_INSUFFICIENT;
+ uint16_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(uint16_t));
+ switch (sizeof(uint16_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(uint16_t)));
+ }
+ buffer->erase(0, sizeof(uint16_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_int16_t(const int16_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ int16_t value_net = value;
+ switch (sizeof(int16_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(int16_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_int16_t(
+ std::string* buffer,
+ int16_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(int16_t))
+ return TPM_RC_INSUFFICIENT;
+ int16_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(int16_t));
+ switch (sizeof(int16_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(int16_t)));
+ }
+ buffer->erase(0, sizeof(int16_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_uint32_t(const uint32_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ uint32_t value_net = value;
+ switch (sizeof(uint32_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(uint32_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_uint32_t(
+ std::string* buffer,
+ uint32_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(uint32_t))
+ return TPM_RC_INSUFFICIENT;
+ uint32_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(uint32_t));
+ switch (sizeof(uint32_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(uint32_t)));
+ }
+ buffer->erase(0, sizeof(uint32_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_int32_t(const int32_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ int32_t value_net = value;
+ switch (sizeof(int32_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(int32_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_int32_t(
+ std::string* buffer,
+ int32_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(int32_t))
+ return TPM_RC_INSUFFICIENT;
+ int32_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(int32_t));
+ switch (sizeof(int32_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(int32_t)));
+ }
+ buffer->erase(0, sizeof(int32_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_uint64_t(const uint64_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ uint64_t value_net = value;
+ switch (sizeof(uint64_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(uint64_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_uint64_t(
+ std::string* buffer,
+ uint64_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(uint64_t))
+ return TPM_RC_INSUFFICIENT;
+ uint64_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(uint64_t));
+ switch (sizeof(uint64_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(uint64_t)));
+ }
+ buffer->erase(0, sizeof(uint64_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_int64_t(const int64_t& value, std::string* buffer) {
+ VLOG(3) << __func__;
+ int64_t value_net = value;
+ switch (sizeof(int64_t)) {
+ case 2:
+ value_net = base::HostToNet16(value);
+ break;
+ case 4:
+ value_net = base::HostToNet32(value);
+ break;
+ case 8:
+ value_net = base::HostToNet64(value);
+ break;
+ default:
+ break;
+ }
+ const char* value_bytes = reinterpret_cast<const char*>(&value_net);
+ buffer->append(value_bytes, sizeof(int64_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Parse_int64_t(
+ std::string* buffer,
+ int64_t* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ if (buffer->size() < sizeof(int64_t))
+ return TPM_RC_INSUFFICIENT;
+ int64_t value_net = 0;
+ memcpy(&value_net, buffer->data(), sizeof(int64_t));
+ switch (sizeof(int64_t)) {
+ case 2:
+ *value = base::NetToHost16(value_net);
+ break;
+ case 4:
+ *value = base::NetToHost32(value_net);
+ break;
+ case 8:
+ *value = base::NetToHost64(value_net);
+ break;
+ default:
+ *value = value_net;
+ }
+ if (value_bytes) {
+ value_bytes->append(buffer->substr(0, sizeof(int64_t)));
+ }
+ buffer->erase(0, sizeof(int64_t));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Serialize_UINT8(
+ const UINT8& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_uint8_t(value, buffer);
+}
+
+TPM_RC Parse_UINT8(
+ std::string* buffer,
+ UINT8* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_uint8_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_BYTE(
+ const BYTE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_uint8_t(value, buffer);
+}
+
+TPM_RC Parse_BYTE(
+ std::string* buffer,
+ BYTE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_uint8_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_INT8(
+ const INT8& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_int8_t(value, buffer);
+}
+
+TPM_RC Parse_INT8(
+ std::string* buffer,
+ INT8* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_int8_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_BOOL(
+ const BOOL& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_int(value, buffer);
+}
+
+TPM_RC Parse_BOOL(
+ std::string* buffer,
+ BOOL* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_int(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_UINT16(
+ const UINT16& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_uint16_t(value, buffer);
+}
+
+TPM_RC Parse_UINT16(
+ std::string* buffer,
+ UINT16* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_uint16_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_INT16(
+ const INT16& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_int16_t(value, buffer);
+}
+
+TPM_RC Parse_INT16(
+ std::string* buffer,
+ INT16* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_int16_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_UINT32(
+ const UINT32& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_uint32_t(value, buffer);
+}
+
+TPM_RC Parse_UINT32(
+ std::string* buffer,
+ UINT32* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_uint32_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_INT32(
+ const INT32& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_int32_t(value, buffer);
+}
+
+TPM_RC Parse_INT32(
+ std::string* buffer,
+ INT32* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_int32_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_UINT64(
+ const UINT64& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_uint64_t(value, buffer);
+}
+
+TPM_RC Parse_UINT64(
+ std::string* buffer,
+ UINT64* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_uint64_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_INT64(
+ const INT64& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_int64_t(value, buffer);
+}
+
+TPM_RC Parse_INT64(
+ std::string* buffer,
+ INT64* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_int64_t(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_ALGORITHM_ID(
+ const TPM_ALGORITHM_ID& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_ALGORITHM_ID(
+ std::string* buffer,
+ TPM_ALGORITHM_ID* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_MODIFIER_INDICATOR(
+ const TPM_MODIFIER_INDICATOR& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_MODIFIER_INDICATOR(
+ std::string* buffer,
+ TPM_MODIFIER_INDICATOR* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_AUTHORIZATION_SIZE(
+ const TPM_AUTHORIZATION_SIZE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_AUTHORIZATION_SIZE(
+ std::string* buffer,
+ TPM_AUTHORIZATION_SIZE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_PARAMETER_SIZE(
+ const TPM_PARAMETER_SIZE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_PARAMETER_SIZE(
+ std::string* buffer,
+ TPM_PARAMETER_SIZE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_KEY_SIZE(
+ const TPM_KEY_SIZE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_KEY_SIZE(
+ std::string* buffer,
+ TPM_KEY_SIZE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_KEY_BITS(
+ const TPM_KEY_BITS& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_KEY_BITS(
+ std::string* buffer,
+ TPM_KEY_BITS* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_HANDLE(
+ const TPM_HANDLE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_HANDLE(
+ std::string* buffer,
+ TPM_HANDLE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM2B_DIGEST(
+ const TPM2B_DIGEST& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_DIGEST(
+ std::string* buffer,
+ TPM2B_DIGEST* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_DIGEST Make_TPM2B_DIGEST(
+ const std::string& bytes) {
+ TPM2B_DIGEST tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_DIGEST));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_DIGEST(
+ const TPM2B_DIGEST& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_NONCE(
+ const TPM2B_NONCE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM2B_DIGEST(value, buffer);
+}
+
+TPM_RC Parse_TPM2B_NONCE(
+ std::string* buffer,
+ TPM2B_NONCE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM2B_DIGEST(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM2B_AUTH(
+ const TPM2B_AUTH& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM2B_DIGEST(value, buffer);
+}
+
+TPM_RC Parse_TPM2B_AUTH(
+ std::string* buffer,
+ TPM2B_AUTH* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM2B_DIGEST(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM2B_OPERAND(
+ const TPM2B_OPERAND& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM2B_DIGEST(value, buffer);
+}
+
+TPM_RC Parse_TPM2B_OPERAND(
+ std::string* buffer,
+ TPM2B_OPERAND* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM2B_DIGEST(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_ALG_ID(
+ const TPM_ALG_ID& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_ALG_ID(
+ std::string* buffer,
+ TPM_ALG_ID* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_HASH(
+ const TPMI_ALG_HASH& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_HASH(
+ std::string* buffer,
+ TPMI_ALG_HASH* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_SCHEME_SIGHASH(
+ const TPMS_SCHEME_SIGHASH& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_SIGHASH(
+ std::string* buffer,
+ TPMS_SCHEME_SIGHASH* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_HMAC(
+ const TPMS_SCHEME_HMAC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
+}
+
+TPM_RC Parse_TPMS_SCHEME_HMAC(
+ std::string* buffer,
+ TPMS_SCHEME_HMAC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_SCHEME_RSASSA(
+ const TPMS_SCHEME_RSASSA& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
+}
+
+TPM_RC Parse_TPMS_SCHEME_RSASSA(
+ std::string* buffer,
+ TPMS_SCHEME_RSASSA* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_SCHEME_RSAPSS(
+ const TPMS_SCHEME_RSAPSS& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
+}
+
+TPM_RC Parse_TPMS_SCHEME_RSAPSS(
+ std::string* buffer,
+ TPMS_SCHEME_RSAPSS* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_SCHEME_ECDSA(
+ const TPMS_SCHEME_ECDSA& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
+}
+
+TPM_RC Parse_TPMS_SCHEME_ECDSA(
+ std::string* buffer,
+ TPMS_SCHEME_ECDSA* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_SCHEME_SM2(
+ const TPMS_SCHEME_SM2& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
+}
+
+TPM_RC Parse_TPMS_SCHEME_SM2(
+ std::string* buffer,
+ TPMS_SCHEME_SM2* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_SCHEME_ECSCHNORR(
+ const TPMS_SCHEME_ECSCHNORR& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPMS_SCHEME_SIGHASH(value, buffer);
+}
+
+TPM_RC Parse_TPMS_SCHEME_ECSCHNORR(
+ std::string* buffer,
+ TPMS_SCHEME_ECSCHNORR* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPMS_SCHEME_SIGHASH(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_YES_NO(
+ const TPMI_YES_NO& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_BYTE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_YES_NO(
+ std::string* buffer,
+ TPMI_YES_NO* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_BYTE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_DH_OBJECT(
+ const TPMI_DH_OBJECT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_DH_OBJECT(
+ std::string* buffer,
+ TPMI_DH_OBJECT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_DH_PERSISTENT(
+ const TPMI_DH_PERSISTENT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_DH_PERSISTENT(
+ std::string* buffer,
+ TPMI_DH_PERSISTENT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_DH_ENTITY(
+ const TPMI_DH_ENTITY& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_DH_ENTITY(
+ std::string* buffer,
+ TPMI_DH_ENTITY* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_DH_PCR(
+ const TPMI_DH_PCR& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_DH_PCR(
+ std::string* buffer,
+ TPMI_DH_PCR* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_SH_AUTH_SESSION(
+ const TPMI_SH_AUTH_SESSION& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_SH_AUTH_SESSION(
+ std::string* buffer,
+ TPMI_SH_AUTH_SESSION* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_SH_HMAC(
+ const TPMI_SH_HMAC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_SH_HMAC(
+ std::string* buffer,
+ TPMI_SH_HMAC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_SH_POLICY(
+ const TPMI_SH_POLICY& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_SH_POLICY(
+ std::string* buffer,
+ TPMI_SH_POLICY* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_DH_CONTEXT(
+ const TPMI_DH_CONTEXT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_DH_CONTEXT(
+ std::string* buffer,
+ TPMI_DH_CONTEXT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_HIERARCHY(
+ const TPMI_RH_HIERARCHY& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_HIERARCHY(
+ std::string* buffer,
+ TPMI_RH_HIERARCHY* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_ENABLES(
+ const TPMI_RH_ENABLES& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_ENABLES(
+ std::string* buffer,
+ TPMI_RH_ENABLES* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_HIERARCHY_AUTH(
+ const TPMI_RH_HIERARCHY_AUTH& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_HIERARCHY_AUTH(
+ std::string* buffer,
+ TPMI_RH_HIERARCHY_AUTH* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_PLATFORM(
+ const TPMI_RH_PLATFORM& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_PLATFORM(
+ std::string* buffer,
+ TPMI_RH_PLATFORM* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_OWNER(
+ const TPMI_RH_OWNER& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_OWNER(
+ std::string* buffer,
+ TPMI_RH_OWNER* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_ENDORSEMENT(
+ const TPMI_RH_ENDORSEMENT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_ENDORSEMENT(
+ std::string* buffer,
+ TPMI_RH_ENDORSEMENT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_PROVISION(
+ const TPMI_RH_PROVISION& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_PROVISION(
+ std::string* buffer,
+ TPMI_RH_PROVISION* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_CLEAR(
+ const TPMI_RH_CLEAR& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_CLEAR(
+ std::string* buffer,
+ TPMI_RH_CLEAR* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_NV_AUTH(
+ const TPMI_RH_NV_AUTH& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_NV_AUTH(
+ std::string* buffer,
+ TPMI_RH_NV_AUTH* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_LOCKOUT(
+ const TPMI_RH_LOCKOUT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_LOCKOUT(
+ std::string* buffer,
+ TPMI_RH_LOCKOUT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RH_NV_INDEX(
+ const TPMI_RH_NV_INDEX& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RH_NV_INDEX(
+ std::string* buffer,
+ TPMI_RH_NV_INDEX* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_ASYM(
+ const TPMI_ALG_ASYM& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_ASYM(
+ std::string* buffer,
+ TPMI_ALG_ASYM* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_SYM(
+ const TPMI_ALG_SYM& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_SYM(
+ std::string* buffer,
+ TPMI_ALG_SYM* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_SYM_OBJECT(
+ const TPMI_ALG_SYM_OBJECT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_SYM_OBJECT(
+ std::string* buffer,
+ TPMI_ALG_SYM_OBJECT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_SYM_MODE(
+ const TPMI_ALG_SYM_MODE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_SYM_MODE(
+ std::string* buffer,
+ TPMI_ALG_SYM_MODE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_KDF(
+ const TPMI_ALG_KDF& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_KDF(
+ std::string* buffer,
+ TPMI_ALG_KDF* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_SIG_SCHEME(
+ const TPMI_ALG_SIG_SCHEME& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_SIG_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_SIG_SCHEME* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ECC_KEY_EXCHANGE(
+ const TPMI_ECC_KEY_EXCHANGE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ECC_KEY_EXCHANGE(
+ std::string* buffer,
+ TPMI_ECC_KEY_EXCHANGE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_ST(
+ const TPM_ST& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_ST(
+ std::string* buffer,
+ TPM_ST* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ST_COMMAND_TAG(
+ const TPMI_ST_COMMAND_TAG& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ST(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ST_COMMAND_TAG(
+ std::string* buffer,
+ TPMI_ST_COMMAND_TAG* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ST(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ST_ATTEST(
+ const TPMI_ST_ATTEST& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ST(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ST_ATTEST(
+ std::string* buffer,
+ TPMI_ST_ATTEST* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ST(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_AES_KEY_BITS(
+ const TPMI_AES_KEY_BITS& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_KEY_BITS(value, buffer);
+}
+
+TPM_RC Parse_TPMI_AES_KEY_BITS(
+ std::string* buffer,
+ TPMI_AES_KEY_BITS* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_KEY_BITS(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_SM4_KEY_BITS(
+ const TPMI_SM4_KEY_BITS& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_KEY_BITS(value, buffer);
+}
+
+TPM_RC Parse_TPMI_SM4_KEY_BITS(
+ std::string* buffer,
+ TPMI_SM4_KEY_BITS* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_KEY_BITS(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_KEYEDHASH_SCHEME(
+ const TPMI_ALG_KEYEDHASH_SCHEME& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_KEYEDHASH_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_KEYEDHASH_SCHEME* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_ASYM_SCHEME(
+ const TPMI_ALG_ASYM_SCHEME& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_ASYM_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_ASYM_SCHEME* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_RSA_SCHEME(
+ const TPMI_ALG_RSA_SCHEME& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_RSA_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_RSA_SCHEME* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_RSA_DECRYPT(
+ const TPMI_ALG_RSA_DECRYPT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_RSA_DECRYPT(
+ std::string* buffer,
+ TPMI_ALG_RSA_DECRYPT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_RSA_KEY_BITS(
+ const TPMI_RSA_KEY_BITS& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_KEY_BITS(value, buffer);
+}
+
+TPM_RC Parse_TPMI_RSA_KEY_BITS(
+ std::string* buffer,
+ TPMI_RSA_KEY_BITS* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_KEY_BITS(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_ECC_SCHEME(
+ const TPMI_ALG_ECC_SCHEME& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_ECC_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_ECC_SCHEME* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_ECC_CURVE(
+ const TPM_ECC_CURVE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_ECC_CURVE(
+ std::string* buffer,
+ TPM_ECC_CURVE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ECC_CURVE(
+ const TPMI_ECC_CURVE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ECC_CURVE(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ECC_CURVE(
+ std::string* buffer,
+ TPMI_ECC_CURVE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ECC_CURVE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMI_ALG_PUBLIC(
+ const TPMI_ALG_PUBLIC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_ALG_ID(value, buffer);
+}
+
+TPM_RC Parse_TPMI_ALG_PUBLIC(
+ std::string* buffer,
+ TPMI_ALG_PUBLIC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_ALG_ID(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_ALGORITHM(
+ const TPMA_ALGORITHM& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPMA_ALGORITHM(
+ std::string* buffer,
+ TPMA_ALGORITHM* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_OBJECT(
+ const TPMA_OBJECT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPMA_OBJECT(
+ std::string* buffer,
+ TPMA_OBJECT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_SESSION(
+ const TPMA_SESSION& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT8(value, buffer);
+}
+
+TPM_RC Parse_TPMA_SESSION(
+ std::string* buffer,
+ TPMA_SESSION* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT8(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_LOCALITY(
+ const TPMA_LOCALITY& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT8(value, buffer);
+}
+
+TPM_RC Parse_TPMA_LOCALITY(
+ std::string* buffer,
+ TPMA_LOCALITY* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT8(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_PERMANENT(
+ const TPMA_PERMANENT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPMA_PERMANENT(
+ std::string* buffer,
+ TPMA_PERMANENT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_STARTUP_CLEAR(
+ const TPMA_STARTUP_CLEAR& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPMA_STARTUP_CLEAR(
+ std::string* buffer,
+ TPMA_STARTUP_CLEAR* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_MEMORY(
+ const TPMA_MEMORY& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPMA_MEMORY(
+ std::string* buffer,
+ TPMA_MEMORY* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_CC(
+ const TPM_CC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_CC(
+ std::string* buffer,
+ TPM_CC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_CC(
+ const TPMA_CC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_CC(value, buffer);
+}
+
+TPM_RC Parse_TPMA_CC(
+ std::string* buffer,
+ TPMA_CC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_CC(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_NV_INDEX(
+ const TPM_NV_INDEX& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_NV_INDEX(
+ std::string* buffer,
+ TPM_NV_INDEX* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMA_NV(
+ const TPMA_NV& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPMA_NV(
+ std::string* buffer,
+ TPMA_NV* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_SPEC(
+ const TPM_SPEC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_SPEC(
+ std::string* buffer,
+ TPM_SPEC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_GENERATED(
+ const TPM_GENERATED& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_GENERATED(
+ std::string* buffer,
+ TPM_GENERATED* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_RC(
+ const TPM_RC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_RC(
+ std::string* buffer,
+ TPM_RC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_CLOCK_ADJUST(
+ const TPM_CLOCK_ADJUST& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_INT8(value, buffer);
+}
+
+TPM_RC Parse_TPM_CLOCK_ADJUST(
+ std::string* buffer,
+ TPM_CLOCK_ADJUST* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_INT8(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_EO(
+ const TPM_EO& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_EO(
+ std::string* buffer,
+ TPM_EO* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_SU(
+ const TPM_SU& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT16(value, buffer);
+}
+
+TPM_RC Parse_TPM_SU(
+ std::string* buffer,
+ TPM_SU* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT16(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_SE(
+ const TPM_SE& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT8(value, buffer);
+}
+
+TPM_RC Parse_TPM_SE(
+ std::string* buffer,
+ TPM_SE* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT8(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_CAP(
+ const TPM_CAP& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_CAP(
+ std::string* buffer,
+ TPM_CAP* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_PT(
+ const TPM_PT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_PT(
+ std::string* buffer,
+ TPM_PT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_PT_PCR(
+ const TPM_PT_PCR& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_PT_PCR(
+ std::string* buffer,
+ TPM_PT_PCR* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_PS(
+ const TPM_PS& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_PS(
+ std::string* buffer,
+ TPM_PS* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_HT(
+ const TPM_HT& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT8(value, buffer);
+}
+
+TPM_RC Parse_TPM_HT(
+ std::string* buffer,
+ TPM_HT* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT8(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_RH(
+ const TPM_RH& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_UINT32(value, buffer);
+}
+
+TPM_RC Parse_TPM_RH(
+ std::string* buffer,
+ TPM_RH* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_UINT32(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPM_HC(
+ const TPM_HC& value,
+ std::string* buffer) {
+ VLOG(3) << __func__;
+ return Serialize_TPM_HANDLE(value, buffer);
+}
+
+TPM_RC Parse_TPM_HC(
+ std::string* buffer,
+ TPM_HC* value,
+ std::string* value_bytes) {
+ VLOG(3) << __func__;
+ return Parse_TPM_HANDLE(buffer, value, value_bytes);
+}
+
+TPM_RC Serialize_TPMS_ALGORITHM_DESCRIPTION(
+ const TPMS_ALGORITHM_DESCRIPTION& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_ALG_ID(value.alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_ALGORITHM(value.attributes, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ALGORITHM_DESCRIPTION(
+ std::string* buffer,
+ TPMS_ALGORITHM_DESCRIPTION* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_ALG_ID(
+ buffer,
+ &value->alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_ALGORITHM(
+ buffer,
+ &value->attributes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_HA(
+ const TPMU_HA& value,
+ TPMI_ALG_HASH selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_SHA384) {
+ if (arraysize(value.sha384) < SHA384_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA384_DIGEST_SIZE; ++i) {
+ result = Serialize_BYTE(value.sha384[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_SHA1) {
+ if (arraysize(value.sha1) < SHA1_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA1_DIGEST_SIZE; ++i) {
+ result = Serialize_BYTE(value.sha1[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_SM3_256) {
+ if (arraysize(value.sm3_256) < SM3_256_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SM3_256_DIGEST_SIZE; ++i) {
+ result = Serialize_BYTE(value.sm3_256[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_SHA256) {
+ if (arraysize(value.sha256) < SHA256_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA256_DIGEST_SIZE; ++i) {
+ result = Serialize_BYTE(value.sha256[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_SHA512) {
+ if (arraysize(value.sha512) < SHA512_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA512_DIGEST_SIZE; ++i) {
+ result = Serialize_BYTE(value.sha512[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_HA(
+ std::string* buffer,
+ TPMI_ALG_HASH selector,
+ TPMU_HA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_SHA384) {
+ if (arraysize(value->sha384) < SHA384_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA384_DIGEST_SIZE; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->sha384[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_SHA1) {
+ if (arraysize(value->sha1) < SHA1_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA1_DIGEST_SIZE; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->sha1[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_SM3_256) {
+ if (arraysize(value->sm3_256) < SM3_256_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SM3_256_DIGEST_SIZE; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->sm3_256[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_SHA256) {
+ if (arraysize(value->sha256) < SHA256_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA256_DIGEST_SIZE; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->sha256[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ }
+
+ if (selector == TPM_ALG_SHA512) {
+ if (arraysize(value->sha512) < SHA512_DIGEST_SIZE) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < SHA512_DIGEST_SIZE; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->sha512[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_HA(
+ const TPMT_HA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_HA(
+ value.digest,
+ value.hash_alg,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_HA(
+ std::string* buffer,
+ TPMT_HA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_HA(
+ buffer,
+ value->hash_alg,
+ &value->digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_DATA(
+ const TPM2B_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_DATA(
+ std::string* buffer,
+ TPM2B_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_DATA Make_TPM2B_DATA(
+ const std::string& bytes) {
+ TPM2B_DATA tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_DATA));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_DATA(
+ const TPM2B_DATA& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_EVENT(
+ const TPM2B_EVENT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_EVENT(
+ std::string* buffer,
+ TPM2B_EVENT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_EVENT Make_TPM2B_EVENT(
+ const std::string& bytes) {
+ TPM2B_EVENT tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_EVENT));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_EVENT(
+ const TPM2B_EVENT& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_MAX_BUFFER(
+ const TPM2B_MAX_BUFFER& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_MAX_BUFFER(
+ std::string* buffer,
+ TPM2B_MAX_BUFFER* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_MAX_BUFFER Make_TPM2B_MAX_BUFFER(
+ const std::string& bytes) {
+ TPM2B_MAX_BUFFER tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_MAX_BUFFER));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_MAX_BUFFER(
+ const TPM2B_MAX_BUFFER& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_MAX_NV_BUFFER(
+ const TPM2B_MAX_NV_BUFFER& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_MAX_NV_BUFFER(
+ std::string* buffer,
+ TPM2B_MAX_NV_BUFFER* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_MAX_NV_BUFFER Make_TPM2B_MAX_NV_BUFFER(
+ const std::string& bytes) {
+ TPM2B_MAX_NV_BUFFER tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_MAX_NV_BUFFER));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_MAX_NV_BUFFER(
+ const TPM2B_MAX_NV_BUFFER& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_TIMEOUT(
+ const TPM2B_TIMEOUT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_TIMEOUT(
+ std::string* buffer,
+ TPM2B_TIMEOUT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_TIMEOUT Make_TPM2B_TIMEOUT(
+ const std::string& bytes) {
+ TPM2B_TIMEOUT tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_TIMEOUT));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_TIMEOUT(
+ const TPM2B_TIMEOUT& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_IV(
+ const TPM2B_IV& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_IV(
+ std::string* buffer,
+ TPM2B_IV* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_IV Make_TPM2B_IV(
+ const std::string& bytes) {
+ TPM2B_IV tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_IV));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_IV(
+ const TPM2B_IV& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_NAME(
+ const TPM2B_NAME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.name) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.name[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_NAME(
+ std::string* buffer,
+ TPM2B_NAME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->name) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->name[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_NAME Make_TPM2B_NAME(
+ const std::string& bytes) {
+ TPM2B_NAME tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.name));
+ memset(&tpm2b, 0, sizeof(TPM2B_NAME));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.name, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_NAME(
+ const TPM2B_NAME& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.name);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_PCR_SELECT(
+ const TPMS_PCR_SELECT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT8(value.sizeof_select, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.pcr_select) < value.sizeof_select) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.sizeof_select; ++i) {
+ result = Serialize_BYTE(value.pcr_select[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_PCR_SELECT(
+ std::string* buffer,
+ TPMS_PCR_SELECT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT8(
+ buffer,
+ &value->sizeof_select,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->pcr_select) < value->sizeof_select) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->sizeof_select; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->pcr_select[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_PCR_SELECTION(
+ const TPMS_PCR_SELECTION& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT8(value.sizeof_select, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.pcr_select) < value.sizeof_select) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.sizeof_select; ++i) {
+ result = Serialize_BYTE(value.pcr_select[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_PCR_SELECTION(
+ std::string* buffer,
+ TPMS_PCR_SELECTION* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT8(
+ buffer,
+ &value->sizeof_select,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->pcr_select) < value->sizeof_select) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->sizeof_select; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->pcr_select[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_TK_CREATION(
+ const TPMT_TK_CREATION& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_ST(value.tag, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_TK_CREATION(
+ std::string* buffer,
+ TPMT_TK_CREATION* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_ST(
+ buffer,
+ &value->tag,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_RH_HIERARCHY(
+ buffer,
+ &value->hierarchy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_TK_VERIFIED(
+ const TPMT_TK_VERIFIED& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_ST(value.tag, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_TK_VERIFIED(
+ std::string* buffer,
+ TPMT_TK_VERIFIED* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_ST(
+ buffer,
+ &value->tag,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_RH_HIERARCHY(
+ buffer,
+ &value->hierarchy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_TK_AUTH(
+ const TPMT_TK_AUTH& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_TK_AUTH(
+ std::string* buffer,
+ TPMT_TK_AUTH* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_RH_HIERARCHY(
+ buffer,
+ &value->hierarchy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_TK_HASHCHECK(
+ const TPMT_TK_HASHCHECK& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_ST(value.tag, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_TK_HASHCHECK(
+ std::string* buffer,
+ TPMT_TK_HASHCHECK* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_ST(
+ buffer,
+ &value->tag,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_RH_HIERARCHY(
+ buffer,
+ &value->hierarchy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_ALG_PROPERTY(
+ const TPMS_ALG_PROPERTY& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_ALG_ID(value.alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_ALGORITHM(value.alg_properties, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ALG_PROPERTY(
+ std::string* buffer,
+ TPMS_ALG_PROPERTY* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_ALG_ID(
+ buffer,
+ &value->alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_ALGORITHM(
+ buffer,
+ &value->alg_properties,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_TAGGED_PROPERTY(
+ const TPMS_TAGGED_PROPERTY& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_PT(value.property, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT32(value.value, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_TAGGED_PROPERTY(
+ std::string* buffer,
+ TPMS_TAGGED_PROPERTY* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_PT(
+ buffer,
+ &value->property,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT32(
+ buffer,
+ &value->value,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_TAGGED_PCR_SELECT(
+ const TPMS_TAGGED_PCR_SELECT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_PT(value.tag, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT8(value.sizeof_select, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.pcr_select) < value.sizeof_select) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.sizeof_select; ++i) {
+ result = Serialize_BYTE(value.pcr_select[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_TAGGED_PCR_SELECT(
+ std::string* buffer,
+ TPMS_TAGGED_PCR_SELECT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_PT(
+ buffer,
+ &value->tag,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT8(
+ buffer,
+ &value->sizeof_select,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->pcr_select) < value->sizeof_select) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->sizeof_select; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->pcr_select[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_CC(
+ const TPML_CC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.command_codes) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPM_CC(value.command_codes[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_CC(
+ std::string* buffer,
+ TPML_CC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->command_codes) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPM_CC(
+ buffer,
+ &value->command_codes[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_CCA(
+ const TPML_CCA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.command_attributes) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPMA_CC(value.command_attributes[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_CCA(
+ std::string* buffer,
+ TPML_CCA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->command_attributes) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPMA_CC(
+ buffer,
+ &value->command_attributes[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_ALG(
+ const TPML_ALG& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.algorithms) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPM_ALG_ID(value.algorithms[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_ALG(
+ std::string* buffer,
+ TPML_ALG* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->algorithms) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPM_ALG_ID(
+ buffer,
+ &value->algorithms[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_HANDLE(
+ const TPML_HANDLE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.handle) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPM_HANDLE(value.handle[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_HANDLE(
+ std::string* buffer,
+ TPML_HANDLE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->handle) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPM_HANDLE(
+ buffer,
+ &value->handle[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_DIGEST(
+ const TPML_DIGEST& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.digests) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPM2B_DIGEST(value.digests[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_DIGEST(
+ std::string* buffer,
+ TPML_DIGEST* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->digests) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->digests[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_DIGEST_VALUES(
+ const TPML_DIGEST_VALUES& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.digests) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPMT_HA(value.digests[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_DIGEST_VALUES(
+ std::string* buffer,
+ TPML_DIGEST_VALUES* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->digests) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPMT_HA(
+ buffer,
+ &value->digests[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_DIGEST_VALUES(
+ const TPM2B_DIGEST_VALUES& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_DIGEST_VALUES(
+ std::string* buffer,
+ TPM2B_DIGEST_VALUES* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_DIGEST_VALUES Make_TPM2B_DIGEST_VALUES(
+ const std::string& bytes) {
+ TPM2B_DIGEST_VALUES tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_DIGEST_VALUES));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_DIGEST_VALUES(
+ const TPM2B_DIGEST_VALUES& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPML_PCR_SELECTION(
+ const TPML_PCR_SELECTION& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.pcr_selections) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPMS_PCR_SELECTION(value.pcr_selections[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_PCR_SELECTION(
+ std::string* buffer,
+ TPML_PCR_SELECTION* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->pcr_selections) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPMS_PCR_SELECTION(
+ buffer,
+ &value->pcr_selections[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_ALG_PROPERTY(
+ const TPML_ALG_PROPERTY& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.alg_properties) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPMS_ALG_PROPERTY(value.alg_properties[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_ALG_PROPERTY(
+ std::string* buffer,
+ TPML_ALG_PROPERTY* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->alg_properties) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPMS_ALG_PROPERTY(
+ buffer,
+ &value->alg_properties[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_TAGGED_TPM_PROPERTY(
+ const TPML_TAGGED_TPM_PROPERTY& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.tpm_property) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPMS_TAGGED_PROPERTY(value.tpm_property[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_TAGGED_TPM_PROPERTY(
+ std::string* buffer,
+ TPML_TAGGED_TPM_PROPERTY* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->tpm_property) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPMS_TAGGED_PROPERTY(
+ buffer,
+ &value->tpm_property[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_TAGGED_PCR_PROPERTY(
+ const TPML_TAGGED_PCR_PROPERTY& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.pcr_property) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPMS_TAGGED_PCR_SELECT(value.pcr_property[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_TAGGED_PCR_PROPERTY(
+ std::string* buffer,
+ TPML_TAGGED_PCR_PROPERTY* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->pcr_property) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPMS_TAGGED_PCR_SELECT(
+ buffer,
+ &value->pcr_property[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPML_ECC_CURVE(
+ const TPML_ECC_CURVE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT32(value.count, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.ecc_curves) < value.count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.count; ++i) {
+ result = Serialize_TPM_ECC_CURVE(value.ecc_curves[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPML_ECC_CURVE(
+ std::string* buffer,
+ TPML_ECC_CURVE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT32(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->ecc_curves) < value->count) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->count; ++i) {
+ result = Parse_TPM_ECC_CURVE(
+ buffer,
+ &value->ecc_curves[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_CAPABILITIES(
+ const TPMU_CAPABILITIES& value,
+ TPM_CAP selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_CAP_PCRS) {
+ result = Serialize_TPML_PCR_SELECTION(value.assigned_pcr, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_TPM_PROPERTIES) {
+ result = Serialize_TPML_TAGGED_TPM_PROPERTY(value.tpm_properties, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_PP_COMMANDS) {
+ result = Serialize_TPML_CC(value.pp_commands, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_AUDIT_COMMANDS) {
+ result = Serialize_TPML_CC(value.audit_commands, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_COMMANDS) {
+ result = Serialize_TPML_CCA(value.command, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_ECC_CURVES) {
+ result = Serialize_TPML_ECC_CURVE(value.ecc_curves, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_PCR_PROPERTIES) {
+ result = Serialize_TPML_TAGGED_PCR_PROPERTY(value.pcr_properties, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_HANDLES) {
+ result = Serialize_TPML_HANDLE(value.handles, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_ALGS) {
+ result = Serialize_TPML_ALG_PROPERTY(value.algorithms, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_CAPABILITIES(
+ std::string* buffer,
+ TPM_CAP selector,
+ TPMU_CAPABILITIES* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_CAP_PCRS) {
+ result = Parse_TPML_PCR_SELECTION(
+ buffer,
+ &value->assigned_pcr,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_TPM_PROPERTIES) {
+ result = Parse_TPML_TAGGED_TPM_PROPERTY(
+ buffer,
+ &value->tpm_properties,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_PP_COMMANDS) {
+ result = Parse_TPML_CC(
+ buffer,
+ &value->pp_commands,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_AUDIT_COMMANDS) {
+ result = Parse_TPML_CC(
+ buffer,
+ &value->audit_commands,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_COMMANDS) {
+ result = Parse_TPML_CCA(
+ buffer,
+ &value->command,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_ECC_CURVES) {
+ result = Parse_TPML_ECC_CURVE(
+ buffer,
+ &value->ecc_curves,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_PCR_PROPERTIES) {
+ result = Parse_TPML_TAGGED_PCR_PROPERTY(
+ buffer,
+ &value->pcr_properties,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_HANDLES) {
+ result = Parse_TPML_HANDLE(
+ buffer,
+ &value->handles,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_CAP_ALGS) {
+ result = Parse_TPML_ALG_PROPERTY(
+ buffer,
+ &value->algorithms,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_CAPABILITY_DATA(
+ const TPMS_CAPABILITY_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_CAP(value.capability, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_CAPABILITIES(
+ value.data,
+ value.capability,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CAPABILITY_DATA(
+ std::string* buffer,
+ TPMS_CAPABILITY_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_CAP(
+ buffer,
+ &value->capability,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_CAPABILITIES(
+ buffer,
+ value->capability,
+ &value->data,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_CLOCK_INFO(
+ const TPMS_CLOCK_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT64(value.clock, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT32(value.reset_count, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT32(value.restart_count, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_YES_NO(value.safe, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CLOCK_INFO(
+ std::string* buffer,
+ TPMS_CLOCK_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT64(
+ buffer,
+ &value->clock,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT32(
+ buffer,
+ &value->reset_count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT32(
+ buffer,
+ &value->restart_count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_YES_NO(
+ buffer,
+ &value->safe,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_TIME_INFO(
+ const TPMS_TIME_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT64(value.time, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMS_CLOCK_INFO(value.clock_info, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_TIME_INFO(
+ std::string* buffer,
+ TPMS_TIME_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT64(
+ buffer,
+ &value->time,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMS_CLOCK_INFO(
+ buffer,
+ &value->clock_info,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_TIME_ATTEST_INFO(
+ const TPMS_TIME_ATTEST_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMS_TIME_INFO(value.time, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT64(value.firmware_version, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_TIME_ATTEST_INFO(
+ std::string* buffer,
+ TPMS_TIME_ATTEST_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMS_TIME_INFO(
+ buffer,
+ &value->time,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT64(
+ buffer,
+ &value->firmware_version,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_CERTIFY_INFO(
+ const TPMS_CERTIFY_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_NAME(value.name, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_NAME(value.qualified_name, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CERTIFY_INFO(
+ std::string* buffer,
+ TPMS_CERTIFY_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->name,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->qualified_name,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_QUOTE_INFO(
+ const TPMS_QUOTE_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPML_PCR_SELECTION(value.pcr_select, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.pcr_digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_QUOTE_INFO(
+ std::string* buffer,
+ TPMS_QUOTE_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPML_PCR_SELECTION(
+ buffer,
+ &value->pcr_select,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->pcr_digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_COMMAND_AUDIT_INFO(
+ const TPMS_COMMAND_AUDIT_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT64(value.audit_counter, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM_ALG_ID(value.digest_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.audit_digest, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.command_digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_COMMAND_AUDIT_INFO(
+ std::string* buffer,
+ TPMS_COMMAND_AUDIT_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT64(
+ buffer,
+ &value->audit_counter,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM_ALG_ID(
+ buffer,
+ &value->digest_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->audit_digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->command_digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SESSION_AUDIT_INFO(
+ const TPMS_SESSION_AUDIT_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_YES_NO(value.exclusive_session, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.session_digest, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SESSION_AUDIT_INFO(
+ std::string* buffer,
+ TPMS_SESSION_AUDIT_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_YES_NO(
+ buffer,
+ &value->exclusive_session,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->session_digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_CREATION_INFO(
+ const TPMS_CREATION_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_NAME(value.object_name, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.creation_hash, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CREATION_INFO(
+ std::string* buffer,
+ TPMS_CREATION_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->object_name,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->creation_hash,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_NV_CERTIFY_INFO(
+ const TPMS_NV_CERTIFY_INFO& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_NAME(value.index_name, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT16(value.offset, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_MAX_NV_BUFFER(value.nv_contents, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_NV_CERTIFY_INFO(
+ std::string* buffer,
+ TPMS_NV_CERTIFY_INFO* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->index_name,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT16(
+ buffer,
+ &value->offset,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_MAX_NV_BUFFER(
+ buffer,
+ &value->nv_contents,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_ATTEST(
+ const TPMU_ATTEST& value,
+ TPMI_ST_ATTEST selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ST_ATTEST_SESSION_AUDIT) {
+ result = Serialize_TPMS_SESSION_AUDIT_INFO(value.session_audit, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_QUOTE) {
+ result = Serialize_TPMS_QUOTE_INFO(value.quote, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_COMMAND_AUDIT) {
+ result = Serialize_TPMS_COMMAND_AUDIT_INFO(value.command_audit, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_CERTIFY) {
+ result = Serialize_TPMS_CERTIFY_INFO(value.certify, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_NV) {
+ result = Serialize_TPMS_NV_CERTIFY_INFO(value.nv, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_TIME) {
+ result = Serialize_TPMS_TIME_ATTEST_INFO(value.time, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_CREATION) {
+ result = Serialize_TPMS_CREATION_INFO(value.creation, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_ATTEST(
+ std::string* buffer,
+ TPMI_ST_ATTEST selector,
+ TPMU_ATTEST* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ST_ATTEST_SESSION_AUDIT) {
+ result = Parse_TPMS_SESSION_AUDIT_INFO(
+ buffer,
+ &value->session_audit,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_QUOTE) {
+ result = Parse_TPMS_QUOTE_INFO(
+ buffer,
+ &value->quote,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_COMMAND_AUDIT) {
+ result = Parse_TPMS_COMMAND_AUDIT_INFO(
+ buffer,
+ &value->command_audit,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_CERTIFY) {
+ result = Parse_TPMS_CERTIFY_INFO(
+ buffer,
+ &value->certify,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_NV) {
+ result = Parse_TPMS_NV_CERTIFY_INFO(
+ buffer,
+ &value->nv,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_TIME) {
+ result = Parse_TPMS_TIME_ATTEST_INFO(
+ buffer,
+ &value->time,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ST_ATTEST_CREATION) {
+ result = Parse_TPMS_CREATION_INFO(
+ buffer,
+ &value->creation,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_ATTEST(
+ const TPMS_ATTEST& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_GENERATED(value.magic, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_ST_ATTEST(value.type, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_NAME(value.qualified_signer, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DATA(value.extra_data, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMS_CLOCK_INFO(value.clock_info, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT64(value.firmware_version, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_ATTEST(
+ value.attested,
+ value.type,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ATTEST(
+ std::string* buffer,
+ TPMS_ATTEST* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_GENERATED(
+ buffer,
+ &value->magic,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_ST_ATTEST(
+ buffer,
+ &value->type,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->qualified_signer,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DATA(
+ buffer,
+ &value->extra_data,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMS_CLOCK_INFO(
+ buffer,
+ &value->clock_info,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT64(
+ buffer,
+ &value->firmware_version,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_ATTEST(
+ buffer,
+ value->type,
+ &value->attested,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_ATTEST(
+ const TPM2B_ATTEST& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.attestation_data) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.attestation_data[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_ATTEST(
+ std::string* buffer,
+ TPM2B_ATTEST* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->attestation_data) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->attestation_data[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_ATTEST Make_TPM2B_ATTEST(
+ const std::string& bytes) {
+ TPM2B_ATTEST tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.attestation_data));
+ memset(&tpm2b, 0, sizeof(TPM2B_ATTEST));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.attestation_data, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_ATTEST(
+ const TPM2B_ATTEST& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.attestation_data);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_AUTH_COMMAND(
+ const TPMS_AUTH_COMMAND& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_SH_AUTH_SESSION(value.session_handle, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_NONCE(value.nonce, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_SESSION(value.session_attributes, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_AUTH(value.hmac, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_AUTH_COMMAND(
+ std::string* buffer,
+ TPMS_AUTH_COMMAND* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_SH_AUTH_SESSION(
+ buffer,
+ &value->session_handle,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_NONCE(
+ buffer,
+ &value->nonce,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_SESSION(
+ buffer,
+ &value->session_attributes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_AUTH(
+ buffer,
+ &value->hmac,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_AUTH_RESPONSE(
+ const TPMS_AUTH_RESPONSE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_NONCE(value.nonce, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_SESSION(value.session_attributes, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_AUTH(value.hmac, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_AUTH_RESPONSE(
+ std::string* buffer,
+ TPMS_AUTH_RESPONSE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_NONCE(
+ buffer,
+ &value->nonce,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_SESSION(
+ buffer,
+ &value->session_attributes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_AUTH(
+ buffer,
+ &value->hmac,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_SYM_KEY_BITS(
+ const TPMU_SYM_KEY_BITS& value,
+ TPMI_ALG_SYM selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_SM4) {
+ result = Serialize_TPMI_SM4_KEY_BITS(value.sm4, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_AES) {
+ result = Serialize_TPMI_AES_KEY_BITS(value.aes, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_XOR) {
+ result = Serialize_TPMI_ALG_HASH(value.xor_, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_SYM_KEY_BITS(
+ std::string* buffer,
+ TPMI_ALG_SYM selector,
+ TPMU_SYM_KEY_BITS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_SM4) {
+ result = Parse_TPMI_SM4_KEY_BITS(
+ buffer,
+ &value->sm4,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_AES) {
+ result = Parse_TPMI_AES_KEY_BITS(
+ buffer,
+ &value->aes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_XOR) {
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->xor_,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_SYM_MODE(
+ const TPMU_SYM_MODE& value,
+ TPMI_ALG_SYM selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_SM4) {
+ result = Serialize_TPMI_ALG_SYM_MODE(value.sm4, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_AES) {
+ result = Serialize_TPMI_ALG_SYM_MODE(value.aes, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_XOR) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_SYM_MODE(
+ std::string* buffer,
+ TPMI_ALG_SYM selector,
+ TPMU_SYM_MODE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_SM4) {
+ result = Parse_TPMI_ALG_SYM_MODE(
+ buffer,
+ &value->sm4,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_AES) {
+ result = Parse_TPMI_ALG_SYM_MODE(
+ buffer,
+ &value->aes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_XOR) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_SYM_DETAILS(
+ const TPMU_SYM_DETAILS& value,
+ TPMI_ALG_SYM selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+ return result;
+}
+
+TPM_RC Parse_TPMU_SYM_DETAILS(
+ std::string* buffer,
+ TPMI_ALG_SYM selector,
+ TPMU_SYM_DETAILS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+ return result;
+}
+
+TPM_RC Serialize_TPMT_SYM_DEF(
+ const TPMT_SYM_DEF& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_SYM(value.algorithm, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SYM_KEY_BITS(
+ value.key_bits,
+ value.algorithm,
+ buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SYM_MODE(
+ value.mode,
+ value.algorithm,
+ buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SYM_DETAILS(
+ value.details,
+ value.algorithm,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_SYM_DEF(
+ std::string* buffer,
+ TPMT_SYM_DEF* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_SYM(
+ buffer,
+ &value->algorithm,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SYM_KEY_BITS(
+ buffer,
+ value->algorithm,
+ &value->key_bits,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SYM_MODE(
+ buffer,
+ value->algorithm,
+ &value->mode,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SYM_DETAILS(
+ buffer,
+ value->algorithm,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_SYM_DEF_OBJECT(
+ const TPMT_SYM_DEF_OBJECT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_SYM_OBJECT(value.algorithm, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SYM_KEY_BITS(
+ value.key_bits,
+ value.algorithm,
+ buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SYM_MODE(
+ value.mode,
+ value.algorithm,
+ buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SYM_DETAILS(
+ value.details,
+ value.algorithm,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_SYM_DEF_OBJECT(
+ std::string* buffer,
+ TPMT_SYM_DEF_OBJECT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_SYM_OBJECT(
+ buffer,
+ &value->algorithm,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SYM_KEY_BITS(
+ buffer,
+ value->algorithm,
+ &value->key_bits,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SYM_MODE(
+ buffer,
+ value->algorithm,
+ &value->mode,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SYM_DETAILS(
+ buffer,
+ value->algorithm,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_SYM_KEY(
+ const TPM2B_SYM_KEY& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_SYM_KEY(
+ std::string* buffer,
+ TPM2B_SYM_KEY* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_SYM_KEY Make_TPM2B_SYM_KEY(
+ const std::string& bytes) {
+ TPM2B_SYM_KEY tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_SYM_KEY));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_SYM_KEY(
+ const TPM2B_SYM_KEY& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_SYMCIPHER_PARMS(
+ const TPMS_SYMCIPHER_PARMS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMT_SYM_DEF_OBJECT(value.sym, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SYMCIPHER_PARMS(
+ std::string* buffer,
+ TPMS_SYMCIPHER_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMT_SYM_DEF_OBJECT(
+ buffer,
+ &value->sym,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_SENSITIVE_DATA(
+ const TPM2B_SENSITIVE_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_SENSITIVE_DATA(
+ std::string* buffer,
+ TPM2B_SENSITIVE_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_SENSITIVE_DATA Make_TPM2B_SENSITIVE_DATA(
+ const std::string& bytes) {
+ TPM2B_SENSITIVE_DATA tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_SENSITIVE_DATA));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_SENSITIVE_DATA(
+ const TPM2B_SENSITIVE_DATA& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_SENSITIVE_CREATE(
+ const TPMS_SENSITIVE_CREATE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_AUTH(value.user_auth, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_SENSITIVE_DATA(value.data, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SENSITIVE_CREATE(
+ std::string* buffer,
+ TPMS_SENSITIVE_CREATE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_AUTH(
+ buffer,
+ &value->user_auth,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_SENSITIVE_DATA(
+ buffer,
+ &value->data,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_SENSITIVE_CREATE(
+ const TPM2B_SENSITIVE_CREATE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ std::string field_bytes;
+ result = Serialize_TPMS_SENSITIVE_CREATE(value.sensitive, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+ return result;
+}
+
+TPM_RC Parse_TPM2B_SENSITIVE_CREATE(
+ std::string* buffer,
+ TPM2B_SENSITIVE_CREATE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMS_SENSITIVE_CREATE(
+ buffer,
+ &value->sensitive,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM2B_SENSITIVE_CREATE Make_TPM2B_SENSITIVE_CREATE(
+ const TPMS_SENSITIVE_CREATE& inner) {
+ TPM2B_SENSITIVE_CREATE tpm2b;
+ tpm2b.size = sizeof(TPMS_SENSITIVE_CREATE);
+ tpm2b.sensitive = inner;
+ return tpm2b;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_XOR(
+ const TPMS_SCHEME_XOR& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_ALG_KDF(value.kdf, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_XOR(
+ std::string* buffer,
+ TPMS_SCHEME_XOR* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_ALG_KDF(
+ buffer,
+ &value->kdf,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_SCHEME_KEYEDHASH(
+ const TPMU_SCHEME_KEYEDHASH& value,
+ TPMI_ALG_KEYEDHASH_SCHEME selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_HMAC) {
+ result = Serialize_TPMS_SCHEME_HMAC(value.hmac, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_XOR) {
+ result = Serialize_TPMS_SCHEME_XOR(value.xor_, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_SCHEME_KEYEDHASH(
+ std::string* buffer,
+ TPMI_ALG_KEYEDHASH_SCHEME selector,
+ TPMU_SCHEME_KEYEDHASH* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_HMAC) {
+ result = Parse_TPMS_SCHEME_HMAC(
+ buffer,
+ &value->hmac,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_XOR) {
+ result = Parse_TPMS_SCHEME_XOR(
+ buffer,
+ &value->xor_,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_KEYEDHASH_SCHEME(
+ const TPMT_KEYEDHASH_SCHEME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_KEYEDHASH_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SCHEME_KEYEDHASH(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_KEYEDHASH_SCHEME(
+ std::string* buffer,
+ TPMT_KEYEDHASH_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_KEYEDHASH_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SCHEME_KEYEDHASH(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_ECDAA(
+ const TPMS_SCHEME_ECDAA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT16(value.count, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_ECDAA(
+ std::string* buffer,
+ TPMS_SCHEME_ECDAA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT16(
+ buffer,
+ &value->count,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_SIG_SCHEME(
+ const TPMU_SIG_SCHEME& value,
+ TPMI_ALG_SIG_SCHEME selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_HMAC) {
+ result = Serialize_TPMS_SCHEME_HMAC(value.hmac, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECSCHNORR) {
+ result = Serialize_TPMS_SCHEME_ECSCHNORR(value.ec_schnorr, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSAPSS) {
+ result = Serialize_TPMS_SCHEME_RSAPSS(value.rsapss, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDAA) {
+ result = Serialize_TPMS_SCHEME_ECDAA(value.ecdaa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSASSA) {
+ result = Serialize_TPMS_SCHEME_RSASSA(value.rsassa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SM2) {
+ result = Serialize_TPMS_SCHEME_SM2(value.sm2, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDSA) {
+ result = Serialize_TPMS_SCHEME_ECDSA(value.ecdsa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_SIG_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_SIG_SCHEME selector,
+ TPMU_SIG_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_HMAC) {
+ result = Parse_TPMS_SCHEME_HMAC(
+ buffer,
+ &value->hmac,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECSCHNORR) {
+ result = Parse_TPMS_SCHEME_ECSCHNORR(
+ buffer,
+ &value->ec_schnorr,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSAPSS) {
+ result = Parse_TPMS_SCHEME_RSAPSS(
+ buffer,
+ &value->rsapss,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDAA) {
+ result = Parse_TPMS_SCHEME_ECDAA(
+ buffer,
+ &value->ecdaa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSASSA) {
+ result = Parse_TPMS_SCHEME_RSASSA(
+ buffer,
+ &value->rsassa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SM2) {
+ result = Parse_TPMS_SCHEME_SM2(
+ buffer,
+ &value->sm2,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDSA) {
+ result = Parse_TPMS_SCHEME_ECDSA(
+ buffer,
+ &value->ecdsa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_SIG_SCHEME(
+ const TPMT_SIG_SCHEME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_SIG_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SIG_SCHEME(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_SIG_SCHEME(
+ std::string* buffer,
+ TPMT_SIG_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_SIG_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SIG_SCHEME(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_OAEP(
+ const TPMS_SCHEME_OAEP& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_OAEP(
+ std::string* buffer,
+ TPMS_SCHEME_OAEP* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_ECDH(
+ const TPMS_SCHEME_ECDH& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_ECDH(
+ std::string* buffer,
+ TPMS_SCHEME_ECDH* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_MGF1(
+ const TPMS_SCHEME_MGF1& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_MGF1(
+ std::string* buffer,
+ TPMS_SCHEME_MGF1* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_KDF1_SP800_56a(
+ const TPMS_SCHEME_KDF1_SP800_56a& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_KDF1_SP800_56a(
+ std::string* buffer,
+ TPMS_SCHEME_KDF1_SP800_56a* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_KDF2(
+ const TPMS_SCHEME_KDF2& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_KDF2(
+ std::string* buffer,
+ TPMS_SCHEME_KDF2* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SCHEME_KDF1_SP800_108(
+ const TPMS_SCHEME_KDF1_SP800_108& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash_alg, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SCHEME_KDF1_SP800_108(
+ std::string* buffer,
+ TPMS_SCHEME_KDF1_SP800_108* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_KDF_SCHEME(
+ const TPMU_KDF_SCHEME& value,
+ TPMI_ALG_KDF selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KDF1_SP800_56a) {
+ result = Serialize_TPMS_SCHEME_KDF1_SP800_56a(value.kdf1_sp800_56a, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_MGF1) {
+ result = Serialize_TPMS_SCHEME_MGF1(value.mgf1, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_KDF1_SP800_108) {
+ result = Serialize_TPMS_SCHEME_KDF1_SP800_108(value.kdf1_sp800_108, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_KDF2) {
+ result = Serialize_TPMS_SCHEME_KDF2(value.kdf2, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_KDF_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_KDF selector,
+ TPMU_KDF_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KDF1_SP800_56a) {
+ result = Parse_TPMS_SCHEME_KDF1_SP800_56a(
+ buffer,
+ &value->kdf1_sp800_56a,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_MGF1) {
+ result = Parse_TPMS_SCHEME_MGF1(
+ buffer,
+ &value->mgf1,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_KDF1_SP800_108) {
+ result = Parse_TPMS_SCHEME_KDF1_SP800_108(
+ buffer,
+ &value->kdf1_sp800_108,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_KDF2) {
+ result = Parse_TPMS_SCHEME_KDF2(
+ buffer,
+ &value->kdf2,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_KDF_SCHEME(
+ const TPMT_KDF_SCHEME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_KDF(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_KDF_SCHEME(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_KDF_SCHEME(
+ std::string* buffer,
+ TPMT_KDF_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_KDF(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_KDF_SCHEME(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_ASYM_SCHEME(
+ const TPMU_ASYM_SCHEME& value,
+ TPMI_ALG_ASYM_SCHEME selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_RSAES) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_ECSCHNORR) {
+ result = Serialize_TPMS_SCHEME_ECSCHNORR(value.ec_schnorr, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_ECDH) {
+ result = Serialize_TPMS_SCHEME_ECDH(value.ecdh, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_OAEP) {
+ result = Serialize_TPMS_SCHEME_OAEP(value.oaep, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSAPSS) {
+ result = Serialize_TPMS_SCHEME_RSAPSS(value.rsapss, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDAA) {
+ result = Serialize_TPMS_SCHEME_ECDAA(value.ecdaa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSASSA) {
+ result = Serialize_TPMS_SCHEME_RSASSA(value.rsassa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SM2) {
+ result = Serialize_TPMS_SCHEME_SM2(value.sm2, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDSA) {
+ result = Serialize_TPMS_SCHEME_ECDSA(value.ecdsa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_ASYM_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_ASYM_SCHEME selector,
+ TPMU_ASYM_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_RSAES) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_ECSCHNORR) {
+ result = Parse_TPMS_SCHEME_ECSCHNORR(
+ buffer,
+ &value->ec_schnorr,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+
+ if (selector == TPM_ALG_ECDH) {
+ result = Parse_TPMS_SCHEME_ECDH(
+ buffer,
+ &value->ecdh,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_OAEP) {
+ result = Parse_TPMS_SCHEME_OAEP(
+ buffer,
+ &value->oaep,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSAPSS) {
+ result = Parse_TPMS_SCHEME_RSAPSS(
+ buffer,
+ &value->rsapss,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDAA) {
+ result = Parse_TPMS_SCHEME_ECDAA(
+ buffer,
+ &value->ecdaa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSASSA) {
+ result = Parse_TPMS_SCHEME_RSASSA(
+ buffer,
+ &value->rsassa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SM2) {
+ result = Parse_TPMS_SCHEME_SM2(
+ buffer,
+ &value->sm2,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDSA) {
+ result = Parse_TPMS_SCHEME_ECDSA(
+ buffer,
+ &value->ecdsa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_ASYM_SCHEME(
+ const TPMT_ASYM_SCHEME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_ASYM_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_ASYM_SCHEME(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_ASYM_SCHEME(
+ std::string* buffer,
+ TPMT_ASYM_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_ASYM_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_ASYM_SCHEME(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_RSA_SCHEME(
+ const TPMT_RSA_SCHEME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_RSA_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_ASYM_SCHEME(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_RSA_SCHEME(
+ std::string* buffer,
+ TPMT_RSA_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_RSA_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_ASYM_SCHEME(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_RSA_DECRYPT(
+ const TPMT_RSA_DECRYPT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_RSA_DECRYPT(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_ASYM_SCHEME(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_RSA_DECRYPT(
+ std::string* buffer,
+ TPMT_RSA_DECRYPT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_RSA_DECRYPT(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_ASYM_SCHEME(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_PUBLIC_KEY_RSA(
+ const TPM2B_PUBLIC_KEY_RSA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_PUBLIC_KEY_RSA(
+ std::string* buffer,
+ TPM2B_PUBLIC_KEY_RSA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_PUBLIC_KEY_RSA Make_TPM2B_PUBLIC_KEY_RSA(
+ const std::string& bytes) {
+ TPM2B_PUBLIC_KEY_RSA tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_PUBLIC_KEY_RSA));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_PUBLIC_KEY_RSA(
+ const TPM2B_PUBLIC_KEY_RSA& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_PRIVATE_KEY_RSA(
+ const TPM2B_PRIVATE_KEY_RSA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_PRIVATE_KEY_RSA(
+ std::string* buffer,
+ TPM2B_PRIVATE_KEY_RSA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_PRIVATE_KEY_RSA Make_TPM2B_PRIVATE_KEY_RSA(
+ const std::string& bytes) {
+ TPM2B_PRIVATE_KEY_RSA tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_PRIVATE_KEY_RSA));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_PRIVATE_KEY_RSA(
+ const TPM2B_PRIVATE_KEY_RSA& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPM2B_ECC_PARAMETER(
+ const TPM2B_ECC_PARAMETER& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_ECC_PARAMETER(
+ std::string* buffer,
+ TPM2B_ECC_PARAMETER* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_ECC_PARAMETER Make_TPM2B_ECC_PARAMETER(
+ const std::string& bytes) {
+ TPM2B_ECC_PARAMETER tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_ECC_PARAMETER));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_ECC_PARAMETER(
+ const TPM2B_ECC_PARAMETER& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_ECC_POINT(
+ const TPMS_ECC_POINT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.x, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.y, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ECC_POINT(
+ std::string* buffer,
+ TPMS_ECC_POINT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->x,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->y,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_ECC_POINT(
+ const TPM2B_ECC_POINT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ std::string field_bytes;
+ result = Serialize_TPMS_ECC_POINT(value.point, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+ return result;
+}
+
+TPM_RC Parse_TPM2B_ECC_POINT(
+ std::string* buffer,
+ TPM2B_ECC_POINT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMS_ECC_POINT(
+ buffer,
+ &value->point,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM2B_ECC_POINT Make_TPM2B_ECC_POINT(
+ const TPMS_ECC_POINT& inner) {
+ TPM2B_ECC_POINT tpm2b;
+ tpm2b.size = sizeof(TPMS_ECC_POINT);
+ tpm2b.point = inner;
+ return tpm2b;
+}
+
+TPM_RC Serialize_TPMT_ECC_SCHEME(
+ const TPMT_ECC_SCHEME& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_ECC_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SIG_SCHEME(
+ value.details,
+ value.scheme,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_ECC_SCHEME(
+ std::string* buffer,
+ TPMT_ECC_SCHEME* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_ECC_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SIG_SCHEME(
+ buffer,
+ value->scheme,
+ &value->details,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_ALGORITHM_DETAIL_ECC(
+ const TPMS_ALGORITHM_DETAIL_ECC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM_ECC_CURVE(value.curve_id, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT16(value.key_size, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_KDF_SCHEME(value.kdf, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_ECC_SCHEME(value.sign, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.p, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.a, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.b, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.g_x, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.g_y, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.n, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.h, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ALGORITHM_DETAIL_ECC(
+ std::string* buffer,
+ TPMS_ALGORITHM_DETAIL_ECC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM_ECC_CURVE(
+ buffer,
+ &value->curve_id,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT16(
+ buffer,
+ &value->key_size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_KDF_SCHEME(
+ buffer,
+ &value->kdf,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_ECC_SCHEME(
+ buffer,
+ &value->sign,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->p,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->a,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->b,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->g_x,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->g_y,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->n,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->h,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SIGNATURE_RSASSA(
+ const TPMS_SIGNATURE_RSASSA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_PUBLIC_KEY_RSA(value.sig, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SIGNATURE_RSASSA(
+ std::string* buffer,
+ TPMS_SIGNATURE_RSASSA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_PUBLIC_KEY_RSA(
+ buffer,
+ &value->sig,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SIGNATURE_RSAPSS(
+ const TPMS_SIGNATURE_RSAPSS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_PUBLIC_KEY_RSA(value.sig, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SIGNATURE_RSAPSS(
+ std::string* buffer,
+ TPMS_SIGNATURE_RSAPSS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_PUBLIC_KEY_RSA(
+ buffer,
+ &value->sig,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_SIGNATURE_ECDSA(
+ const TPMS_SIGNATURE_ECDSA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_HASH(value.hash, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.signature_r, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_ECC_PARAMETER(value.signature_s, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_SIGNATURE_ECDSA(
+ std::string* buffer,
+ TPMS_SIGNATURE_ECDSA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->hash,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->signature_r,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->signature_s,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_SIGNATURE(
+ const TPMU_SIGNATURE& value,
+ TPMI_ALG_SIG_SCHEME selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_HMAC) {
+ result = Serialize_TPMT_HA(value.hmac, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECSCHNORR) {
+ result = Serialize_TPMS_SIGNATURE_ECDSA(value.ecschnorr, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSAPSS) {
+ result = Serialize_TPMS_SIGNATURE_RSAPSS(value.rsapss, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDAA) {
+ result = Serialize_TPMS_SIGNATURE_ECDSA(value.ecdaa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSASSA) {
+ result = Serialize_TPMS_SIGNATURE_RSASSA(value.rsassa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SM2) {
+ result = Serialize_TPMS_SIGNATURE_ECDSA(value.sm2, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDSA) {
+ result = Serialize_TPMS_SIGNATURE_ECDSA(value.ecdsa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_SIGNATURE(
+ std::string* buffer,
+ TPMI_ALG_SIG_SCHEME selector,
+ TPMU_SIGNATURE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_HMAC) {
+ result = Parse_TPMT_HA(
+ buffer,
+ &value->hmac,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECSCHNORR) {
+ result = Parse_TPMS_SIGNATURE_ECDSA(
+ buffer,
+ &value->ecschnorr,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSAPSS) {
+ result = Parse_TPMS_SIGNATURE_RSAPSS(
+ buffer,
+ &value->rsapss,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDAA) {
+ result = Parse_TPMS_SIGNATURE_ECDSA(
+ buffer,
+ &value->ecdaa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSASSA) {
+ result = Parse_TPMS_SIGNATURE_RSASSA(
+ buffer,
+ &value->rsassa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SM2) {
+ result = Parse_TPMS_SIGNATURE_ECDSA(
+ buffer,
+ &value->sm2,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECDSA) {
+ result = Parse_TPMS_SIGNATURE_ECDSA(
+ buffer,
+ &value->ecdsa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_NULL) {
+ // Do nothing.
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_SIGNATURE(
+ const TPMT_SIGNATURE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_SIG_SCHEME(value.sig_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SIGNATURE(
+ value.signature,
+ value.sig_alg,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_SIGNATURE(
+ std::string* buffer,
+ TPMT_SIGNATURE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_SIG_SCHEME(
+ buffer,
+ &value->sig_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SIGNATURE(
+ buffer,
+ value->sig_alg,
+ &value->signature,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_ENCRYPTED_SECRET(
+ const TPM2B_ENCRYPTED_SECRET& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.secret) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.secret[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_ENCRYPTED_SECRET(
+ std::string* buffer,
+ TPM2B_ENCRYPTED_SECRET* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->secret) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->secret[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_ENCRYPTED_SECRET Make_TPM2B_ENCRYPTED_SECRET(
+ const std::string& bytes) {
+ TPM2B_ENCRYPTED_SECRET tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.secret));
+ memset(&tpm2b, 0, sizeof(TPM2B_ENCRYPTED_SECRET));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.secret, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_ENCRYPTED_SECRET(
+ const TPM2B_ENCRYPTED_SECRET& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.secret);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_KEYEDHASH_PARMS(
+ const TPMS_KEYEDHASH_PARMS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMT_KEYEDHASH_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_KEYEDHASH_PARMS(
+ std::string* buffer,
+ TPMS_KEYEDHASH_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMT_KEYEDHASH_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_ASYM_PARMS(
+ const TPMS_ASYM_PARMS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMT_SYM_DEF_OBJECT(value.symmetric, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_ASYM_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ASYM_PARMS(
+ std::string* buffer,
+ TPMS_ASYM_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMT_SYM_DEF_OBJECT(
+ buffer,
+ &value->symmetric,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_ASYM_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_RSA_PARMS(
+ const TPMS_RSA_PARMS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMT_SYM_DEF_OBJECT(value.symmetric, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_RSA_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_RSA_KEY_BITS(value.key_bits, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT32(value.exponent, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_RSA_PARMS(
+ std::string* buffer,
+ TPMS_RSA_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMT_SYM_DEF_OBJECT(
+ buffer,
+ &value->symmetric,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_RSA_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_RSA_KEY_BITS(
+ buffer,
+ &value->key_bits,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT32(
+ buffer,
+ &value->exponent,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_ECC_PARMS(
+ const TPMS_ECC_PARMS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMT_SYM_DEF_OBJECT(value.symmetric, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_ECC_SCHEME(value.scheme, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_ECC_CURVE(value.curve_id, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_KDF_SCHEME(value.kdf, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_ECC_PARMS(
+ std::string* buffer,
+ TPMS_ECC_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMT_SYM_DEF_OBJECT(
+ buffer,
+ &value->symmetric,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_ECC_SCHEME(
+ buffer,
+ &value->scheme,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_ECC_CURVE(
+ buffer,
+ &value->curve_id,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_KDF_SCHEME(
+ buffer,
+ &value->kdf,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_PUBLIC_PARMS(
+ const TPMU_PUBLIC_PARMS& value,
+ TPMI_ALG_PUBLIC selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KEYEDHASH) {
+ result = Serialize_TPMS_KEYEDHASH_PARMS(value.keyed_hash_detail, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSA) {
+ result = Serialize_TPMS_RSA_PARMS(value.rsa_detail, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SYMCIPHER) {
+ result = Serialize_TPMS_SYMCIPHER_PARMS(value.sym_detail, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECC) {
+ result = Serialize_TPMS_ECC_PARMS(value.ecc_detail, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_PUBLIC_PARMS(
+ std::string* buffer,
+ TPMI_ALG_PUBLIC selector,
+ TPMU_PUBLIC_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KEYEDHASH) {
+ result = Parse_TPMS_KEYEDHASH_PARMS(
+ buffer,
+ &value->keyed_hash_detail,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSA) {
+ result = Parse_TPMS_RSA_PARMS(
+ buffer,
+ &value->rsa_detail,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SYMCIPHER) {
+ result = Parse_TPMS_SYMCIPHER_PARMS(
+ buffer,
+ &value->sym_detail,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECC) {
+ result = Parse_TPMS_ECC_PARMS(
+ buffer,
+ &value->ecc_detail,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_PUBLIC_PARMS(
+ const TPMT_PUBLIC_PARMS& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_PUBLIC(value.type, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_PUBLIC_PARMS(
+ value.parameters,
+ value.type,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_PUBLIC_PARMS(
+ std::string* buffer,
+ TPMT_PUBLIC_PARMS* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_PUBLIC(
+ buffer,
+ &value->type,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_PUBLIC_PARMS(
+ buffer,
+ value->type,
+ &value->parameters,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMU_PUBLIC_ID(
+ const TPMU_PUBLIC_ID& value,
+ TPMI_ALG_PUBLIC selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KEYEDHASH) {
+ result = Serialize_TPM2B_DIGEST(value.keyed_hash, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSA) {
+ result = Serialize_TPM2B_PUBLIC_KEY_RSA(value.rsa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SYMCIPHER) {
+ result = Serialize_TPM2B_DIGEST(value.sym, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECC) {
+ result = Serialize_TPMS_ECC_POINT(value.ecc, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_PUBLIC_ID(
+ std::string* buffer,
+ TPMI_ALG_PUBLIC selector,
+ TPMU_PUBLIC_ID* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KEYEDHASH) {
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->keyed_hash,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSA) {
+ result = Parse_TPM2B_PUBLIC_KEY_RSA(
+ buffer,
+ &value->rsa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SYMCIPHER) {
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->sym,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECC) {
+ result = Parse_TPMS_ECC_POINT(
+ buffer,
+ &value->ecc,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_PUBLIC(
+ const TPMT_PUBLIC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_PUBLIC(value.type, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_ALG_HASH(value.name_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_OBJECT(value.object_attributes, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.auth_policy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_PUBLIC_PARMS(
+ value.parameters,
+ value.type,
+ buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_PUBLIC_ID(
+ value.unique,
+ value.type,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_PUBLIC(
+ std::string* buffer,
+ TPMT_PUBLIC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_PUBLIC(
+ buffer,
+ &value->type,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->name_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_OBJECT(
+ buffer,
+ &value->object_attributes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->auth_policy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_PUBLIC_PARMS(
+ buffer,
+ value->type,
+ &value->parameters,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_PUBLIC_ID(
+ buffer,
+ value->type,
+ &value->unique,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_PUBLIC(
+ const TPM2B_PUBLIC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ std::string field_bytes;
+ result = Serialize_TPMT_PUBLIC(value.public_area, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+ return result;
+}
+
+TPM_RC Parse_TPM2B_PUBLIC(
+ std::string* buffer,
+ TPM2B_PUBLIC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_PUBLIC(
+ buffer,
+ &value->public_area,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM2B_PUBLIC Make_TPM2B_PUBLIC(
+ const TPMT_PUBLIC& inner) {
+ TPM2B_PUBLIC tpm2b;
+ tpm2b.size = sizeof(TPMT_PUBLIC);
+ tpm2b.public_area = inner;
+ return tpm2b;
+}
+
+TPM_RC Serialize_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ const TPM2B_PRIVATE_VENDOR_SPECIFIC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ std::string* buffer,
+ TPM2B_PRIVATE_VENDOR_SPECIFIC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_PRIVATE_VENDOR_SPECIFIC Make_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ const std::string& bytes) {
+ TPM2B_PRIVATE_VENDOR_SPECIFIC tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_PRIVATE_VENDOR_SPECIFIC));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ const TPM2B_PRIVATE_VENDOR_SPECIFIC& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMU_SENSITIVE_COMPOSITE(
+ const TPMU_SENSITIVE_COMPOSITE& value,
+ TPMI_ALG_PUBLIC selector,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KEYEDHASH) {
+ result = Serialize_TPM2B_SENSITIVE_DATA(value.bits, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSA) {
+ result = Serialize_TPM2B_PRIVATE_KEY_RSA(value.rsa, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SYMCIPHER) {
+ result = Serialize_TPM2B_SYM_KEY(value.sym, buffer);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECC) {
+ result = Serialize_TPM2B_ECC_PARAMETER(value.ecc, buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMU_SENSITIVE_COMPOSITE(
+ std::string* buffer,
+ TPMI_ALG_PUBLIC selector,
+ TPMU_SENSITIVE_COMPOSITE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ if (selector == TPM_ALG_KEYEDHASH) {
+ result = Parse_TPM2B_SENSITIVE_DATA(
+ buffer,
+ &value->bits,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_RSA) {
+ result = Parse_TPM2B_PRIVATE_KEY_RSA(
+ buffer,
+ &value->rsa,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_SYMCIPHER) {
+ result = Parse_TPM2B_SYM_KEY(
+ buffer,
+ &value->sym,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+
+ if (selector == TPM_ALG_ECC) {
+ result = Parse_TPM2B_ECC_PARAMETER(
+ buffer,
+ &value->ecc,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMT_SENSITIVE(
+ const TPMT_SENSITIVE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_ALG_PUBLIC(value.sensitive_type, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_AUTH(value.auth_value, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.seed_value, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMU_SENSITIVE_COMPOSITE(
+ value.sensitive,
+ value.sensitive_type,
+ buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMT_SENSITIVE(
+ std::string* buffer,
+ TPMT_SENSITIVE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_ALG_PUBLIC(
+ buffer,
+ &value->sensitive_type,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_AUTH(
+ buffer,
+ &value->auth_value,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->seed_value,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMU_SENSITIVE_COMPOSITE(
+ buffer,
+ value->sensitive_type,
+ &value->sensitive,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_SENSITIVE(
+ const TPM2B_SENSITIVE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ std::string field_bytes;
+ result = Serialize_TPMT_SENSITIVE(value.sensitive_area, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+ return result;
+}
+
+TPM_RC Parse_TPM2B_SENSITIVE(
+ std::string* buffer,
+ TPM2B_SENSITIVE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_SENSITIVE(
+ buffer,
+ &value->sensitive_area,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM2B_SENSITIVE Make_TPM2B_SENSITIVE(
+ const TPMT_SENSITIVE& inner) {
+ TPM2B_SENSITIVE tpm2b;
+ tpm2b.size = sizeof(TPMT_SENSITIVE);
+ tpm2b.sensitive_area = inner;
+ return tpm2b;
+}
+
+TPM_RC Serialize__PRIVATE(
+ const _PRIVATE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_DIGEST(value.integrity_outer, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.integrity_inner, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMT_SENSITIVE(value.sensitive, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse__PRIVATE(
+ std::string* buffer,
+ _PRIVATE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->integrity_outer,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->integrity_inner,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMT_SENSITIVE(
+ buffer,
+ &value->sensitive,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_PRIVATE(
+ const TPM2B_PRIVATE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_PRIVATE(
+ std::string* buffer,
+ TPM2B_PRIVATE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_PRIVATE Make_TPM2B_PRIVATE(
+ const std::string& bytes) {
+ TPM2B_PRIVATE tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_PRIVATE));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_PRIVATE(
+ const TPM2B_PRIVATE& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize__ID_OBJECT(
+ const _ID_OBJECT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_DIGEST(value.integrity_hmac, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.enc_identity, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse__ID_OBJECT(
+ std::string* buffer,
+ _ID_OBJECT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->integrity_hmac,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->enc_identity,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_ID_OBJECT(
+ const TPM2B_ID_OBJECT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.credential) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.credential[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_ID_OBJECT(
+ std::string* buffer,
+ TPM2B_ID_OBJECT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->credential) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->credential[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_ID_OBJECT Make_TPM2B_ID_OBJECT(
+ const std::string& bytes) {
+ TPM2B_ID_OBJECT tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.credential));
+ memset(&tpm2b, 0, sizeof(TPM2B_ID_OBJECT));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.credential, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_ID_OBJECT(
+ const TPM2B_ID_OBJECT& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.credential);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_NV_PUBLIC(
+ const TPMS_NV_PUBLIC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPMI_RH_NV_INDEX(value.nv_index, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_ALG_HASH(value.name_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_NV(value.attributes, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.auth_policy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_UINT16(value.data_size, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_NV_PUBLIC(
+ std::string* buffer,
+ TPMS_NV_PUBLIC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPMI_RH_NV_INDEX(
+ buffer,
+ &value->nv_index,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_ALG_HASH(
+ buffer,
+ &value->name_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_NV(
+ buffer,
+ &value->attributes,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->auth_policy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_UINT16(
+ buffer,
+ &value->data_size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_NV_PUBLIC(
+ const TPM2B_NV_PUBLIC& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ std::string field_bytes;
+ result = Serialize_TPMS_NV_PUBLIC(value.nv_public, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+ return result;
+}
+
+TPM_RC Parse_TPM2B_NV_PUBLIC(
+ std::string* buffer,
+ TPM2B_NV_PUBLIC* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMS_NV_PUBLIC(
+ buffer,
+ &value->nv_public,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM2B_NV_PUBLIC Make_TPM2B_NV_PUBLIC(
+ const TPMS_NV_PUBLIC& inner) {
+ TPM2B_NV_PUBLIC tpm2b;
+ tpm2b.size = sizeof(TPMS_NV_PUBLIC);
+ tpm2b.nv_public = inner;
+ return tpm2b;
+}
+
+TPM_RC Serialize_TPM2B_CONTEXT_SENSITIVE(
+ const TPM2B_CONTEXT_SENSITIVE& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_CONTEXT_SENSITIVE(
+ std::string* buffer,
+ TPM2B_CONTEXT_SENSITIVE* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_CONTEXT_SENSITIVE Make_TPM2B_CONTEXT_SENSITIVE(
+ const std::string& bytes) {
+ TPM2B_CONTEXT_SENSITIVE tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_CONTEXT_SENSITIVE));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_CONTEXT_SENSITIVE(
+ const TPM2B_CONTEXT_SENSITIVE& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_CONTEXT_DATA(
+ const TPMS_CONTEXT_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPM2B_DIGEST(value.integrity, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_CONTEXT_SENSITIVE(value.encrypted, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CONTEXT_DATA(
+ std::string* buffer,
+ TPMS_CONTEXT_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->integrity,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_CONTEXT_SENSITIVE(
+ buffer,
+ &value->encrypted,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_CONTEXT_DATA(
+ const TPM2B_CONTEXT_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT16(value.size, buffer);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value.buffer) < value.size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value.size; ++i) {
+ result = Serialize_BYTE(value.buffer[i], buffer);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM_RC Parse_TPM2B_CONTEXT_DATA(
+ std::string* buffer,
+ TPM2B_CONTEXT_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ if (arraysize(value->buffer) < value->size) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ for (uint32_t i = 0; i < value->size; ++i) {
+ result = Parse_BYTE(
+ buffer,
+ &value->buffer[i],
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ }
+ return result;
+}
+
+TPM2B_CONTEXT_DATA Make_TPM2B_CONTEXT_DATA(
+ const std::string& bytes) {
+ TPM2B_CONTEXT_DATA tpm2b;
+ CHECK(bytes.size() <= sizeof(tpm2b.buffer));
+ memset(&tpm2b, 0, sizeof(TPM2B_CONTEXT_DATA));
+ tpm2b.size = bytes.size();
+ memcpy(tpm2b.buffer, bytes.data(), bytes.size());
+ return tpm2b;
+}
+
+std::string StringFrom_TPM2B_CONTEXT_DATA(
+ const TPM2B_CONTEXT_DATA& tpm2b) {
+ const char* char_buffer = reinterpret_cast<const char*>(
+ tpm2b.buffer);
+ return std::string(char_buffer, tpm2b.size);
+}
+
+TPM_RC Serialize_TPMS_CONTEXT(
+ const TPMS_CONTEXT& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_UINT64(value.sequence, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_DH_CONTEXT(value.saved_handle, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMI_RH_HIERARCHY(value.hierarchy, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_CONTEXT_DATA(value.context_blob, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CONTEXT(
+ std::string* buffer,
+ TPMS_CONTEXT* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT64(
+ buffer,
+ &value->sequence,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_DH_CONTEXT(
+ buffer,
+ &value->saved_handle,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMI_RH_HIERARCHY(
+ buffer,
+ &value->hierarchy,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_CONTEXT_DATA(
+ buffer,
+ &value->context_blob,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPMS_CREATION_DATA(
+ const TPMS_CREATION_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Serialize_TPML_PCR_SELECTION(value.pcr_select, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DIGEST(value.pcr_digest, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPMA_LOCALITY(value.locality, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM_ALG_ID(value.parent_name_alg, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_NAME(value.parent_name, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_NAME(value.parent_qualified_name, buffer);
+ if (result) {
+ return result;
+ }
+
+ result = Serialize_TPM2B_DATA(value.outside_info, buffer);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Parse_TPMS_CREATION_DATA(
+ std::string* buffer,
+ TPMS_CREATION_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_TPML_PCR_SELECTION(
+ buffer,
+ &value->pcr_select,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DIGEST(
+ buffer,
+ &value->pcr_digest,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMA_LOCALITY(
+ buffer,
+ &value->locality,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM_ALG_ID(
+ buffer,
+ &value->parent_name_alg,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->parent_name,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_NAME(
+ buffer,
+ &value->parent_qualified_name,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPM2B_DATA(
+ buffer,
+ &value->outside_info,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM_RC Serialize_TPM2B_CREATION_DATA(
+ const TPM2B_CREATION_DATA& value,
+ std::string* buffer) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ std::string field_bytes;
+ result = Serialize_TPMS_CREATION_DATA(value.creation_data, &field_bytes);
+ if (result) {
+ return result;
+ }
+ std::string size_bytes;
+ result = Serialize_UINT16(field_bytes.size(), &size_bytes);
+ if (result) {
+ return result;
+ }
+ buffer->append(size_bytes + field_bytes);
+ return result;
+}
+
+TPM_RC Parse_TPM2B_CREATION_DATA(
+ std::string* buffer,
+ TPM2B_CREATION_DATA* value,
+ std::string* value_bytes) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ VLOG(3) << __func__;
+
+ result = Parse_UINT16(
+ buffer,
+ &value->size,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+
+ result = Parse_TPMS_CREATION_DATA(
+ buffer,
+ &value->creation_data,
+ value_bytes);
+ if (result) {
+ return result;
+ }
+ return result;
+}
+
+TPM2B_CREATION_DATA Make_TPM2B_CREATION_DATA(
+ const TPMS_CREATION_DATA& inner) {
+ TPM2B_CREATION_DATA tpm2b;
+ tpm2b.size = sizeof(TPMS_CREATION_DATA);
+ tpm2b.creation_data = inner;
+ return tpm2b;
+}
+
+TPM_RC Tpm::SerializeCommand_Startup(
+ const TPM_SU& startup_type,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Startup;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string startup_type_bytes;
+ rc = Serialize_TPM_SU(
+ startup_type,
+ &startup_type_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(startup_type_bytes.data(),
+ startup_type_bytes.size());
+ parameter_section_bytes += startup_type_bytes;
+ command_size += startup_type_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Startup(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Startup;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void StartupErrorCallback(
+ const Tpm::StartupResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void StartupResponseParser(
+ const Tpm::StartupResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(StartupErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_Startup(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::Startup(
+ const TPM_SU& startup_type,
+ AuthorizationDelegate* authorization_delegate,
+ const StartupResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(StartupErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(StartupResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Startup(
+ startup_type,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::StartupSync(
+ const TPM_SU& startup_type,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Startup(
+ startup_type,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Startup(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Shutdown(
+ const TPM_SU& shutdown_type,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Shutdown;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string shutdown_type_bytes;
+ rc = Serialize_TPM_SU(
+ shutdown_type,
+ &shutdown_type_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(shutdown_type_bytes.data(),
+ shutdown_type_bytes.size());
+ parameter_section_bytes += shutdown_type_bytes;
+ command_size += shutdown_type_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Shutdown(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Shutdown;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ShutdownErrorCallback(
+ const Tpm::ShutdownResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ShutdownResponseParser(
+ const Tpm::ShutdownResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ShutdownErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_Shutdown(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::Shutdown(
+ const TPM_SU& shutdown_type,
+ AuthorizationDelegate* authorization_delegate,
+ const ShutdownResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ShutdownErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ShutdownResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Shutdown(
+ shutdown_type,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ShutdownSync(
+ const TPM_SU& shutdown_type,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Shutdown(
+ shutdown_type,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Shutdown(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_SelfTest(
+ const TPMI_YES_NO& full_test,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_SelfTest;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string full_test_bytes;
+ rc = Serialize_TPMI_YES_NO(
+ full_test,
+ &full_test_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(full_test_bytes.data(),
+ full_test_bytes.size());
+ parameter_section_bytes += full_test_bytes;
+ command_size += full_test_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_SelfTest(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_SelfTest;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SelfTestErrorCallback(
+ const Tpm::SelfTestResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void SelfTestResponseParser(
+ const Tpm::SelfTestResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SelfTestErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_SelfTest(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::SelfTest(
+ const TPMI_YES_NO& full_test,
+ AuthorizationDelegate* authorization_delegate,
+ const SelfTestResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SelfTestErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SelfTestResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_SelfTest(
+ full_test,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SelfTestSync(
+ const TPMI_YES_NO& full_test,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_SelfTest(
+ full_test,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_SelfTest(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_IncrementalSelfTest(
+ const TPML_ALG& to_test,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_IncrementalSelfTest;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string to_test_bytes;
+ rc = Serialize_TPML_ALG(
+ to_test,
+ &to_test_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(to_test_bytes.data(),
+ to_test_bytes.size());
+ parameter_section_bytes += to_test_bytes;
+ command_size += to_test_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_IncrementalSelfTest(
+ const std::string& response,
+ TPML_ALG* to_do_list,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_IncrementalSelfTest;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string to_do_list_bytes;
+ rc = Parse_TPML_ALG(
+ &buffer,
+ to_do_list,
+ &to_do_list_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void IncrementalSelfTestErrorCallback(
+ const Tpm::IncrementalSelfTestResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPML_ALG());
+}
+
+void IncrementalSelfTestResponseParser(
+ const Tpm::IncrementalSelfTestResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(IncrementalSelfTestErrorCallback, callback);
+ TPML_ALG to_do_list;
+ TPM_RC rc = Tpm::ParseResponse_IncrementalSelfTest(
+ response,
+ &to_do_list,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ to_do_list);
+}
+
+void Tpm::IncrementalSelfTest(
+ const TPML_ALG& to_test,
+ AuthorizationDelegate* authorization_delegate,
+ const IncrementalSelfTestResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(IncrementalSelfTestErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(IncrementalSelfTestResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_IncrementalSelfTest(
+ to_test,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::IncrementalSelfTestSync(
+ const TPML_ALG& to_test,
+ TPML_ALG* to_do_list,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_IncrementalSelfTest(
+ to_test,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_IncrementalSelfTest(
+ response,
+ to_do_list,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_GetTestResult(
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_GetTestResult;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_GetTestResult(
+ const std::string& response,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM_RC* test_result,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_GetTestResult;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_data_bytes;
+ rc = Parse_TPM2B_MAX_BUFFER(
+ &buffer,
+ out_data,
+ &out_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string test_result_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ test_result,
+ &test_result_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_data_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_data_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_MAX_BUFFER(
+ &out_data_bytes,
+ out_data,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void GetTestResultErrorCallback(
+ const Tpm::GetTestResultResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_MAX_BUFFER(),
+ TPM_RC());
+}
+
+void GetTestResultResponseParser(
+ const Tpm::GetTestResultResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetTestResultErrorCallback, callback);
+ TPM2B_MAX_BUFFER out_data;
+ TPM_RC test_result;
+ TPM_RC rc = Tpm::ParseResponse_GetTestResult(
+ response,
+ &out_data,
+ &test_result,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_data,
+ test_result);
+}
+
+void Tpm::GetTestResult(
+ AuthorizationDelegate* authorization_delegate,
+ const GetTestResultResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetTestResultErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(GetTestResultResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetTestResult(
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::GetTestResultSync(
+ TPM2B_MAX_BUFFER* out_data,
+ TPM_RC* test_result,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetTestResult(
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_GetTestResult(
+ response,
+ out_data,
+ test_result,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_StartAuthSession(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_StartAuthSession;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string tpm_key_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ tpm_key,
+ &tpm_key_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string bind_bytes;
+ rc = Serialize_TPMI_DH_ENTITY(
+ bind,
+ &bind_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nonce_caller_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ nonce_caller,
+ &nonce_caller_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string encrypted_salt_bytes;
+ rc = Serialize_TPM2B_ENCRYPTED_SECRET(
+ encrypted_salt,
+ &encrypted_salt_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string session_type_bytes;
+ rc = Serialize_TPM_SE(
+ session_type,
+ &session_type_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string symmetric_bytes;
+ rc = Serialize_TPMT_SYM_DEF(
+ symmetric,
+ &symmetric_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_hash_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ auth_hash,
+ &auth_hash_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = nonce_caller_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ nonce_caller_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(tpm_key_name.data(),
+ tpm_key_name.size());
+ handle_section_bytes += tpm_key_bytes;
+ command_size += tpm_key_bytes.size();
+ hash->Update(bind_name.data(),
+ bind_name.size());
+ handle_section_bytes += bind_bytes;
+ command_size += bind_bytes.size();
+ hash->Update(nonce_caller_bytes.data(),
+ nonce_caller_bytes.size());
+ parameter_section_bytes += nonce_caller_bytes;
+ command_size += nonce_caller_bytes.size();
+ hash->Update(encrypted_salt_bytes.data(),
+ encrypted_salt_bytes.size());
+ parameter_section_bytes += encrypted_salt_bytes;
+ command_size += encrypted_salt_bytes.size();
+ hash->Update(session_type_bytes.data(),
+ session_type_bytes.size());
+ parameter_section_bytes += session_type_bytes;
+ command_size += session_type_bytes.size();
+ hash->Update(symmetric_bytes.data(),
+ symmetric_bytes.size());
+ parameter_section_bytes += symmetric_bytes;
+ command_size += symmetric_bytes.size();
+ hash->Update(auth_hash_bytes.data(),
+ auth_hash_bytes.size());
+ parameter_section_bytes += auth_hash_bytes;
+ command_size += auth_hash_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_StartAuthSession(
+ const std::string& response,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string session_handle_bytes;
+ rc = Parse_TPMI_SH_AUTH_SESSION(
+ &buffer,
+ session_handle,
+ &session_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_StartAuthSession;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string nonce_tpm_bytes;
+ rc = Parse_TPM2B_NONCE(
+ &buffer,
+ nonce_tpm,
+ &nonce_tpm_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = nonce_tpm_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ nonce_tpm_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_NONCE(
+ &nonce_tpm_bytes,
+ nonce_tpm,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void StartAuthSessionErrorCallback(
+ const Tpm::StartAuthSessionResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMI_SH_AUTH_SESSION(),
+ TPM2B_NONCE());
+}
+
+void StartAuthSessionResponseParser(
+ const Tpm::StartAuthSessionResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(StartAuthSessionErrorCallback, callback);
+ TPMI_SH_AUTH_SESSION session_handle;
+ TPM2B_NONCE nonce_tpm;
+ TPM_RC rc = Tpm::ParseResponse_StartAuthSession(
+ response,
+ &session_handle,
+ &nonce_tpm,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ session_handle,
+ nonce_tpm);
+}
+
+void Tpm::StartAuthSession(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const StartAuthSessionResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(StartAuthSessionErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(StartAuthSessionResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_StartAuthSession(
+ tpm_key,
+ tpm_key_name,
+ bind,
+ bind_name,
+ nonce_caller,
+ encrypted_salt,
+ session_type,
+ symmetric,
+ auth_hash,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::StartAuthSessionSync(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_StartAuthSession(
+ tpm_key,
+ tpm_key_name,
+ bind,
+ bind_name,
+ nonce_caller,
+ encrypted_salt,
+ session_type,
+ symmetric,
+ auth_hash,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_StartAuthSession(
+ response,
+ session_handle,
+ nonce_tpm,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyRestart(
+ const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyRestart;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string session_handle_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ session_handle,
+ &session_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(session_handle_name.data(),
+ session_handle_name.size());
+ handle_section_bytes += session_handle_bytes;
+ command_size += session_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyRestart(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyRestart;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyRestartErrorCallback(
+ const Tpm::PolicyRestartResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyRestartResponseParser(
+ const Tpm::PolicyRestartResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyRestartErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyRestart(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyRestart(
+ const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyRestartResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyRestartErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyRestartResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyRestart(
+ session_handle,
+ session_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyRestartSync(
+ const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyRestart(
+ session_handle,
+ session_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyRestart(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Create(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Create;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string parent_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ parent_handle,
+ &parent_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_sensitive_bytes;
+ rc = Serialize_TPM2B_SENSITIVE_CREATE(
+ in_sensitive,
+ &in_sensitive_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_public_bytes;
+ rc = Serialize_TPM2B_PUBLIC(
+ in_public,
+ &in_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string outside_info_bytes;
+ rc = Serialize_TPM2B_DATA(
+ outside_info,
+ &outside_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_pcr_bytes;
+ rc = Serialize_TPML_PCR_SELECTION(
+ creation_pcr,
+ &creation_pcr_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_sensitive_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_sensitive_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(parent_handle_name.data(),
+ parent_handle_name.size());
+ handle_section_bytes += parent_handle_bytes;
+ command_size += parent_handle_bytes.size();
+ hash->Update(in_sensitive_bytes.data(),
+ in_sensitive_bytes.size());
+ parameter_section_bytes += in_sensitive_bytes;
+ command_size += in_sensitive_bytes.size();
+ hash->Update(in_public_bytes.data(),
+ in_public_bytes.size());
+ parameter_section_bytes += in_public_bytes;
+ command_size += in_public_bytes.size();
+ hash->Update(outside_info_bytes.data(),
+ outside_info_bytes.size());
+ parameter_section_bytes += outside_info_bytes;
+ command_size += outside_info_bytes.size();
+ hash->Update(creation_pcr_bytes.data(),
+ creation_pcr_bytes.size());
+ parameter_section_bytes += creation_pcr_bytes;
+ command_size += creation_pcr_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Create(
+ const std::string& response,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Create;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_private_bytes;
+ rc = Parse_TPM2B_PRIVATE(
+ &buffer,
+ out_private,
+ &out_private_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string out_public_bytes;
+ rc = Parse_TPM2B_PUBLIC(
+ &buffer,
+ out_public,
+ &out_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_data_bytes;
+ rc = Parse_TPM2B_CREATION_DATA(
+ &buffer,
+ creation_data,
+ &creation_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_hash_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ creation_hash,
+ &creation_hash_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_ticket_bytes;
+ rc = Parse_TPMT_TK_CREATION(
+ &buffer,
+ creation_ticket,
+ &creation_ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_private_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_private_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PRIVATE(
+ &out_private_bytes,
+ out_private,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void CreateErrorCallback(
+ const Tpm::CreateResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PRIVATE(),
+ TPM2B_PUBLIC(),
+ TPM2B_CREATION_DATA(),
+ TPM2B_DIGEST(),
+ TPMT_TK_CREATION());
+}
+
+void CreateResponseParser(
+ const Tpm::CreateResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CreateErrorCallback, callback);
+ TPM2B_PRIVATE out_private;
+ TPM2B_PUBLIC out_public;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ TPM_RC rc = Tpm::ParseResponse_Create(
+ response,
+ &out_private,
+ &out_public,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_private,
+ out_public,
+ creation_data,
+ creation_hash,
+ creation_ticket);
+}
+
+void Tpm::Create(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ AuthorizationDelegate* authorization_delegate,
+ const CreateResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CreateErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(CreateResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Create(
+ parent_handle,
+ parent_handle_name,
+ in_sensitive,
+ in_public,
+ outside_info,
+ creation_pcr,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::CreateSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Create(
+ parent_handle,
+ parent_handle_name,
+ in_sensitive,
+ in_public,
+ outside_info,
+ creation_pcr,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Create(
+ response,
+ out_private,
+ out_public,
+ creation_data,
+ creation_hash,
+ creation_ticket,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Load(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Load;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string parent_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ parent_handle,
+ &parent_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_private_bytes;
+ rc = Serialize_TPM2B_PRIVATE(
+ in_private,
+ &in_private_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_public_bytes;
+ rc = Serialize_TPM2B_PUBLIC(
+ in_public,
+ &in_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_private_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_private_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(parent_handle_name.data(),
+ parent_handle_name.size());
+ handle_section_bytes += parent_handle_bytes;
+ command_size += parent_handle_bytes.size();
+ hash->Update(in_private_bytes.data(),
+ in_private_bytes.size());
+ parameter_section_bytes += in_private_bytes;
+ command_size += in_private_bytes.size();
+ hash->Update(in_public_bytes.data(),
+ in_public_bytes.size());
+ parameter_section_bytes += in_public_bytes;
+ command_size += in_public_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Load(
+ const std::string& response,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string object_handle_bytes;
+ rc = Parse_TPM_HANDLE(
+ &buffer,
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_Load;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string name_bytes;
+ rc = Parse_TPM2B_NAME(
+ &buffer,
+ name,
+ &name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = name_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ name_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_NAME(
+ &name_bytes,
+ name,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void LoadErrorCallback(
+ const Tpm::LoadResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM_HANDLE(),
+ TPM2B_NAME());
+}
+
+void LoadResponseParser(
+ const Tpm::LoadResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(LoadErrorCallback, callback);
+ TPM_HANDLE object_handle;
+ TPM2B_NAME name;
+ TPM_RC rc = Tpm::ParseResponse_Load(
+ response,
+ &object_handle,
+ &name,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ object_handle,
+ name);
+}
+
+void Tpm::Load(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ AuthorizationDelegate* authorization_delegate,
+ const LoadResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(LoadErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(LoadResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Load(
+ parent_handle,
+ parent_handle_name,
+ in_private,
+ in_public,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::LoadSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Load(
+ parent_handle,
+ parent_handle_name,
+ in_private,
+ in_public,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Load(
+ response,
+ object_handle,
+ name,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_LoadExternal(
+ const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_LoadExternal;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_private_bytes;
+ rc = Serialize_TPM2B_SENSITIVE(
+ in_private,
+ &in_private_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_public_bytes;
+ rc = Serialize_TPM2B_PUBLIC(
+ in_public,
+ &in_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hierarchy_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY(
+ hierarchy,
+ &hierarchy_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_private_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_private_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(in_private_bytes.data(),
+ in_private_bytes.size());
+ parameter_section_bytes += in_private_bytes;
+ command_size += in_private_bytes.size();
+ hash->Update(in_public_bytes.data(),
+ in_public_bytes.size());
+ parameter_section_bytes += in_public_bytes;
+ command_size += in_public_bytes.size();
+ hash->Update(hierarchy_bytes.data(),
+ hierarchy_bytes.size());
+ parameter_section_bytes += hierarchy_bytes;
+ command_size += hierarchy_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_LoadExternal(
+ const std::string& response,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string object_handle_bytes;
+ rc = Parse_TPM_HANDLE(
+ &buffer,
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_LoadExternal;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string name_bytes;
+ rc = Parse_TPM2B_NAME(
+ &buffer,
+ name,
+ &name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = name_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ name_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_NAME(
+ &name_bytes,
+ name,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void LoadExternalErrorCallback(
+ const Tpm::LoadExternalResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM_HANDLE(),
+ TPM2B_NAME());
+}
+
+void LoadExternalResponseParser(
+ const Tpm::LoadExternalResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(LoadExternalErrorCallback, callback);
+ TPM_HANDLE object_handle;
+ TPM2B_NAME name;
+ TPM_RC rc = Tpm::ParseResponse_LoadExternal(
+ response,
+ &object_handle,
+ &name,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ object_handle,
+ name);
+}
+
+void Tpm::LoadExternal(
+ const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const LoadExternalResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(LoadExternalErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(LoadExternalResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_LoadExternal(
+ in_private,
+ in_public,
+ hierarchy,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::LoadExternalSync(
+ const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_LoadExternal(
+ in_private,
+ in_public,
+ hierarchy,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_LoadExternal(
+ response,
+ object_handle,
+ name,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ReadPublic(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ReadPublic;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(object_handle_name.data(),
+ object_handle_name.size());
+ handle_section_bytes += object_handle_bytes;
+ command_size += object_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ReadPublic(
+ const std::string& response,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_NAME* name,
+ TPM2B_NAME* qualified_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ReadPublic;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_public_bytes;
+ rc = Parse_TPM2B_PUBLIC(
+ &buffer,
+ out_public,
+ &out_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string name_bytes;
+ rc = Parse_TPM2B_NAME(
+ &buffer,
+ name,
+ &name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualified_name_bytes;
+ rc = Parse_TPM2B_NAME(
+ &buffer,
+ qualified_name,
+ &qualified_name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_public_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_public_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PUBLIC(
+ &out_public_bytes,
+ out_public,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ReadPublicErrorCallback(
+ const Tpm::ReadPublicResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PUBLIC(),
+ TPM2B_NAME(),
+ TPM2B_NAME());
+}
+
+void ReadPublicResponseParser(
+ const Tpm::ReadPublicResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ReadPublicErrorCallback, callback);
+ TPM2B_PUBLIC out_public;
+ TPM2B_NAME name;
+ TPM2B_NAME qualified_name;
+ TPM_RC rc = Tpm::ParseResponse_ReadPublic(
+ response,
+ &out_public,
+ &name,
+ &qualified_name,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_public,
+ name,
+ qualified_name);
+}
+
+void Tpm::ReadPublic(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ReadPublicResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ReadPublicErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ReadPublicResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ReadPublic(
+ object_handle,
+ object_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ReadPublicSync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_NAME* name,
+ TPM2B_NAME* qualified_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ReadPublic(
+ object_handle,
+ object_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ReadPublic(
+ response,
+ out_public,
+ name,
+ qualified_name,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ActivateCredential(
+ const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ActivateCredential;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string activate_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ activate_handle,
+ &activate_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string credential_blob_bytes;
+ rc = Serialize_TPM2B_ID_OBJECT(
+ credential_blob,
+ &credential_blob_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string secret_bytes;
+ rc = Serialize_TPM2B_ENCRYPTED_SECRET(
+ secret,
+ &secret_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = credential_blob_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ credential_blob_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(activate_handle_name.data(),
+ activate_handle_name.size());
+ handle_section_bytes += activate_handle_bytes;
+ command_size += activate_handle_bytes.size();
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(credential_blob_bytes.data(),
+ credential_blob_bytes.size());
+ parameter_section_bytes += credential_blob_bytes;
+ command_size += credential_blob_bytes.size();
+ hash->Update(secret_bytes.data(),
+ secret_bytes.size());
+ parameter_section_bytes += secret_bytes;
+ command_size += secret_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ActivateCredential(
+ const std::string& response,
+ TPM2B_DIGEST* cert_info,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ActivateCredential;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string cert_info_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ cert_info,
+ &cert_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = cert_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ cert_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DIGEST(
+ &cert_info_bytes,
+ cert_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ActivateCredentialErrorCallback(
+ const Tpm::ActivateCredentialResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DIGEST());
+}
+
+void ActivateCredentialResponseParser(
+ const Tpm::ActivateCredentialResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ActivateCredentialErrorCallback, callback);
+ TPM2B_DIGEST cert_info;
+ TPM_RC rc = Tpm::ParseResponse_ActivateCredential(
+ response,
+ &cert_info,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ cert_info);
+}
+
+void Tpm::ActivateCredential(
+ const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ AuthorizationDelegate* authorization_delegate,
+ const ActivateCredentialResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ActivateCredentialErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ActivateCredentialResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ActivateCredential(
+ activate_handle,
+ activate_handle_name,
+ key_handle,
+ key_handle_name,
+ credential_blob,
+ secret,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ActivateCredentialSync(
+ const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ TPM2B_DIGEST* cert_info,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ActivateCredential(
+ activate_handle,
+ activate_handle_name,
+ key_handle,
+ key_handle_name,
+ credential_blob,
+ secret,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ActivateCredential(
+ response,
+ cert_info,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_MakeCredential(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_MakeCredential;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ handle,
+ &handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string credential_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ credential,
+ &credential_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_name_bytes;
+ rc = Serialize_TPM2B_NAME(
+ object_name,
+ &object_name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = credential_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ credential_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(handle_name.data(),
+ handle_name.size());
+ handle_section_bytes += handle_bytes;
+ command_size += handle_bytes.size();
+ hash->Update(credential_bytes.data(),
+ credential_bytes.size());
+ parameter_section_bytes += credential_bytes;
+ command_size += credential_bytes.size();
+ hash->Update(object_name_bytes.data(),
+ object_name_bytes.size());
+ parameter_section_bytes += object_name_bytes;
+ command_size += object_name_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_MakeCredential(
+ const std::string& response,
+ TPM2B_ID_OBJECT* credential_blob,
+ TPM2B_ENCRYPTED_SECRET* secret,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_MakeCredential;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string credential_blob_bytes;
+ rc = Parse_TPM2B_ID_OBJECT(
+ &buffer,
+ credential_blob,
+ &credential_blob_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string secret_bytes;
+ rc = Parse_TPM2B_ENCRYPTED_SECRET(
+ &buffer,
+ secret,
+ &secret_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = credential_blob_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ credential_blob_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ID_OBJECT(
+ &credential_blob_bytes,
+ credential_blob,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void MakeCredentialErrorCallback(
+ const Tpm::MakeCredentialResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ID_OBJECT(),
+ TPM2B_ENCRYPTED_SECRET());
+}
+
+void MakeCredentialResponseParser(
+ const Tpm::MakeCredentialResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(MakeCredentialErrorCallback, callback);
+ TPM2B_ID_OBJECT credential_blob;
+ TPM2B_ENCRYPTED_SECRET secret;
+ TPM_RC rc = Tpm::ParseResponse_MakeCredential(
+ response,
+ &credential_blob,
+ &secret,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ credential_blob,
+ secret);
+}
+
+void Tpm::MakeCredential(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ AuthorizationDelegate* authorization_delegate,
+ const MakeCredentialResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(MakeCredentialErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(MakeCredentialResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_MakeCredential(
+ handle,
+ handle_name,
+ credential,
+ object_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::MakeCredentialSync(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ TPM2B_ID_OBJECT* credential_blob,
+ TPM2B_ENCRYPTED_SECRET* secret,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_MakeCredential(
+ handle,
+ handle_name,
+ credential,
+ object_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_MakeCredential(
+ response,
+ credential_blob,
+ secret,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Unseal(
+ const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Unseal;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string item_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ item_handle,
+ &item_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(item_handle_name.data(),
+ item_handle_name.size());
+ handle_section_bytes += item_handle_bytes;
+ command_size += item_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Unseal(
+ const std::string& response,
+ TPM2B_SENSITIVE_DATA* out_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Unseal;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_data_bytes;
+ rc = Parse_TPM2B_SENSITIVE_DATA(
+ &buffer,
+ out_data,
+ &out_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_data_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_data_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_SENSITIVE_DATA(
+ &out_data_bytes,
+ out_data,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void UnsealErrorCallback(
+ const Tpm::UnsealResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_SENSITIVE_DATA());
+}
+
+void UnsealResponseParser(
+ const Tpm::UnsealResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(UnsealErrorCallback, callback);
+ TPM2B_SENSITIVE_DATA out_data;
+ TPM_RC rc = Tpm::ParseResponse_Unseal(
+ response,
+ &out_data,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_data);
+}
+
+void Tpm::Unseal(
+ const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const UnsealResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(UnsealErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(UnsealResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Unseal(
+ item_handle,
+ item_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::UnsealSync(
+ const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ TPM2B_SENSITIVE_DATA* out_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Unseal(
+ item_handle,
+ item_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Unseal(
+ response,
+ out_data,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ObjectChangeAuth(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ObjectChangeAuth;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string parent_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ parent_handle,
+ &parent_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_auth_bytes;
+ rc = Serialize_TPM2B_AUTH(
+ new_auth,
+ &new_auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = new_auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ new_auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(object_handle_name.data(),
+ object_handle_name.size());
+ handle_section_bytes += object_handle_bytes;
+ command_size += object_handle_bytes.size();
+ hash->Update(parent_handle_name.data(),
+ parent_handle_name.size());
+ handle_section_bytes += parent_handle_bytes;
+ command_size += parent_handle_bytes.size();
+ hash->Update(new_auth_bytes.data(),
+ new_auth_bytes.size());
+ parameter_section_bytes += new_auth_bytes;
+ command_size += new_auth_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ObjectChangeAuth(
+ const std::string& response,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ObjectChangeAuth;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_private_bytes;
+ rc = Parse_TPM2B_PRIVATE(
+ &buffer,
+ out_private,
+ &out_private_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_private_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_private_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PRIVATE(
+ &out_private_bytes,
+ out_private,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ObjectChangeAuthErrorCallback(
+ const Tpm::ObjectChangeAuthResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PRIVATE());
+}
+
+void ObjectChangeAuthResponseParser(
+ const Tpm::ObjectChangeAuthResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ObjectChangeAuthErrorCallback, callback);
+ TPM2B_PRIVATE out_private;
+ TPM_RC rc = Tpm::ParseResponse_ObjectChangeAuth(
+ response,
+ &out_private,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_private);
+}
+
+void Tpm::ObjectChangeAuth(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const ObjectChangeAuthResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ObjectChangeAuthErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ObjectChangeAuthResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ObjectChangeAuth(
+ object_handle,
+ object_handle_name,
+ parent_handle,
+ parent_handle_name,
+ new_auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ObjectChangeAuthSync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ObjectChangeAuth(
+ object_handle,
+ object_handle_name,
+ parent_handle,
+ parent_handle_name,
+ new_auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ObjectChangeAuth(
+ response,
+ out_private,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Duplicate(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Duplicate;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_parent_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ new_parent_handle,
+ &new_parent_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string encryption_key_in_bytes;
+ rc = Serialize_TPM2B_DATA(
+ encryption_key_in,
+ &encryption_key_in_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string symmetric_alg_bytes;
+ rc = Serialize_TPMT_SYM_DEF_OBJECT(
+ symmetric_alg,
+ &symmetric_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = encryption_key_in_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ encryption_key_in_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(object_handle_name.data(),
+ object_handle_name.size());
+ handle_section_bytes += object_handle_bytes;
+ command_size += object_handle_bytes.size();
+ hash->Update(new_parent_handle_name.data(),
+ new_parent_handle_name.size());
+ handle_section_bytes += new_parent_handle_bytes;
+ command_size += new_parent_handle_bytes.size();
+ hash->Update(encryption_key_in_bytes.data(),
+ encryption_key_in_bytes.size());
+ parameter_section_bytes += encryption_key_in_bytes;
+ command_size += encryption_key_in_bytes.size();
+ hash->Update(symmetric_alg_bytes.data(),
+ symmetric_alg_bytes.size());
+ parameter_section_bytes += symmetric_alg_bytes;
+ command_size += symmetric_alg_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Duplicate(
+ const std::string& response,
+ TPM2B_DATA* encryption_key_out,
+ TPM2B_PRIVATE* duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Duplicate;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string encryption_key_out_bytes;
+ rc = Parse_TPM2B_DATA(
+ &buffer,
+ encryption_key_out,
+ &encryption_key_out_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string duplicate_bytes;
+ rc = Parse_TPM2B_PRIVATE(
+ &buffer,
+ duplicate,
+ &duplicate_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string out_sym_seed_bytes;
+ rc = Parse_TPM2B_ENCRYPTED_SECRET(
+ &buffer,
+ out_sym_seed,
+ &out_sym_seed_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = encryption_key_out_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ encryption_key_out_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DATA(
+ &encryption_key_out_bytes,
+ encryption_key_out,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void DuplicateErrorCallback(
+ const Tpm::DuplicateResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DATA(),
+ TPM2B_PRIVATE(),
+ TPM2B_ENCRYPTED_SECRET());
+}
+
+void DuplicateResponseParser(
+ const Tpm::DuplicateResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(DuplicateErrorCallback, callback);
+ TPM2B_DATA encryption_key_out;
+ TPM2B_PRIVATE duplicate;
+ TPM2B_ENCRYPTED_SECRET out_sym_seed;
+ TPM_RC rc = Tpm::ParseResponse_Duplicate(
+ response,
+ &encryption_key_out,
+ &duplicate,
+ &out_sym_seed,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ encryption_key_out,
+ duplicate,
+ out_sym_seed);
+}
+
+void Tpm::Duplicate(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const DuplicateResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(DuplicateErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(DuplicateResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Duplicate(
+ object_handle,
+ object_handle_name,
+ new_parent_handle,
+ new_parent_handle_name,
+ encryption_key_in,
+ symmetric_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::DuplicateSync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ TPM2B_DATA* encryption_key_out,
+ TPM2B_PRIVATE* duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Duplicate(
+ object_handle,
+ object_handle_name,
+ new_parent_handle,
+ new_parent_handle_name,
+ encryption_key_in,
+ symmetric_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Duplicate(
+ response,
+ encryption_key_out,
+ duplicate,
+ out_sym_seed,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Rewrap(
+ const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Rewrap;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string old_parent_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ old_parent,
+ &old_parent_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_parent_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ new_parent,
+ &new_parent_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_duplicate_bytes;
+ rc = Serialize_TPM2B_PRIVATE(
+ in_duplicate,
+ &in_duplicate_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string name_bytes;
+ rc = Serialize_TPM2B_NAME(
+ name,
+ &name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_sym_seed_bytes;
+ rc = Serialize_TPM2B_ENCRYPTED_SECRET(
+ in_sym_seed,
+ &in_sym_seed_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_duplicate_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_duplicate_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(old_parent_name.data(),
+ old_parent_name.size());
+ handle_section_bytes += old_parent_bytes;
+ command_size += old_parent_bytes.size();
+ hash->Update(new_parent_name.data(),
+ new_parent_name.size());
+ handle_section_bytes += new_parent_bytes;
+ command_size += new_parent_bytes.size();
+ hash->Update(in_duplicate_bytes.data(),
+ in_duplicate_bytes.size());
+ parameter_section_bytes += in_duplicate_bytes;
+ command_size += in_duplicate_bytes.size();
+ hash->Update(name_bytes.data(),
+ name_bytes.size());
+ parameter_section_bytes += name_bytes;
+ command_size += name_bytes.size();
+ hash->Update(in_sym_seed_bytes.data(),
+ in_sym_seed_bytes.size());
+ parameter_section_bytes += in_sym_seed_bytes;
+ command_size += in_sym_seed_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Rewrap(
+ const std::string& response,
+ TPM2B_PRIVATE* out_duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Rewrap;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_duplicate_bytes;
+ rc = Parse_TPM2B_PRIVATE(
+ &buffer,
+ out_duplicate,
+ &out_duplicate_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string out_sym_seed_bytes;
+ rc = Parse_TPM2B_ENCRYPTED_SECRET(
+ &buffer,
+ out_sym_seed,
+ &out_sym_seed_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_duplicate_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_duplicate_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PRIVATE(
+ &out_duplicate_bytes,
+ out_duplicate,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void RewrapErrorCallback(
+ const Tpm::RewrapResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PRIVATE(),
+ TPM2B_ENCRYPTED_SECRET());
+}
+
+void RewrapResponseParser(
+ const Tpm::RewrapResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(RewrapErrorCallback, callback);
+ TPM2B_PRIVATE out_duplicate;
+ TPM2B_ENCRYPTED_SECRET out_sym_seed;
+ TPM_RC rc = Tpm::ParseResponse_Rewrap(
+ response,
+ &out_duplicate,
+ &out_sym_seed,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_duplicate,
+ out_sym_seed);
+}
+
+void Tpm::Rewrap(
+ const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ AuthorizationDelegate* authorization_delegate,
+ const RewrapResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(RewrapErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(RewrapResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Rewrap(
+ old_parent,
+ old_parent_name,
+ new_parent,
+ new_parent_name,
+ in_duplicate,
+ name,
+ in_sym_seed,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::RewrapSync(
+ const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ TPM2B_PRIVATE* out_duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Rewrap(
+ old_parent,
+ old_parent_name,
+ new_parent,
+ new_parent_name,
+ in_duplicate,
+ name,
+ in_sym_seed,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Rewrap(
+ response,
+ out_duplicate,
+ out_sym_seed,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Import(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Import;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string parent_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ parent_handle,
+ &parent_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string encryption_key_bytes;
+ rc = Serialize_TPM2B_DATA(
+ encryption_key,
+ &encryption_key_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_public_bytes;
+ rc = Serialize_TPM2B_PUBLIC(
+ object_public,
+ &object_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string duplicate_bytes;
+ rc = Serialize_TPM2B_PRIVATE(
+ duplicate,
+ &duplicate_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_sym_seed_bytes;
+ rc = Serialize_TPM2B_ENCRYPTED_SECRET(
+ in_sym_seed,
+ &in_sym_seed_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string symmetric_alg_bytes;
+ rc = Serialize_TPMT_SYM_DEF_OBJECT(
+ symmetric_alg,
+ &symmetric_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = encryption_key_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ encryption_key_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(parent_handle_name.data(),
+ parent_handle_name.size());
+ handle_section_bytes += parent_handle_bytes;
+ command_size += parent_handle_bytes.size();
+ hash->Update(encryption_key_bytes.data(),
+ encryption_key_bytes.size());
+ parameter_section_bytes += encryption_key_bytes;
+ command_size += encryption_key_bytes.size();
+ hash->Update(object_public_bytes.data(),
+ object_public_bytes.size());
+ parameter_section_bytes += object_public_bytes;
+ command_size += object_public_bytes.size();
+ hash->Update(duplicate_bytes.data(),
+ duplicate_bytes.size());
+ parameter_section_bytes += duplicate_bytes;
+ command_size += duplicate_bytes.size();
+ hash->Update(in_sym_seed_bytes.data(),
+ in_sym_seed_bytes.size());
+ parameter_section_bytes += in_sym_seed_bytes;
+ command_size += in_sym_seed_bytes.size();
+ hash->Update(symmetric_alg_bytes.data(),
+ symmetric_alg_bytes.size());
+ parameter_section_bytes += symmetric_alg_bytes;
+ command_size += symmetric_alg_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Import(
+ const std::string& response,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Import;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_private_bytes;
+ rc = Parse_TPM2B_PRIVATE(
+ &buffer,
+ out_private,
+ &out_private_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_private_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_private_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PRIVATE(
+ &out_private_bytes,
+ out_private,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ImportErrorCallback(
+ const Tpm::ImportResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PRIVATE());
+}
+
+void ImportResponseParser(
+ const Tpm::ImportResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ImportErrorCallback, callback);
+ TPM2B_PRIVATE out_private;
+ TPM_RC rc = Tpm::ParseResponse_Import(
+ response,
+ &out_private,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_private);
+}
+
+void Tpm::Import(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const ImportResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ImportErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ImportResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Import(
+ parent_handle,
+ parent_handle_name,
+ encryption_key,
+ object_public,
+ duplicate,
+ in_sym_seed,
+ symmetric_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ImportSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Import(
+ parent_handle,
+ parent_handle_name,
+ encryption_key,
+ object_public,
+ duplicate,
+ in_sym_seed,
+ symmetric_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Import(
+ response,
+ out_private,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_RSA_Encrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_RSA_Encrypt;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string message_bytes;
+ rc = Serialize_TPM2B_PUBLIC_KEY_RSA(
+ message,
+ &message_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_RSA_DECRYPT(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string label_bytes;
+ rc = Serialize_TPM2B_DATA(
+ label,
+ &label_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = message_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ message_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(message_bytes.data(),
+ message_bytes.size());
+ parameter_section_bytes += message_bytes;
+ command_size += message_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(label_bytes.data(),
+ label_bytes.size());
+ parameter_section_bytes += label_bytes;
+ command_size += label_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_RSA_Encrypt(
+ const std::string& response,
+ TPM2B_PUBLIC_KEY_RSA* out_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_RSA_Encrypt;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_data_bytes;
+ rc = Parse_TPM2B_PUBLIC_KEY_RSA(
+ &buffer,
+ out_data,
+ &out_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_data_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_data_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PUBLIC_KEY_RSA(
+ &out_data_bytes,
+ out_data,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void RSA_EncryptErrorCallback(
+ const Tpm::RSA_EncryptResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PUBLIC_KEY_RSA());
+}
+
+void RSA_EncryptResponseParser(
+ const Tpm::RSA_EncryptResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(RSA_EncryptErrorCallback, callback);
+ TPM2B_PUBLIC_KEY_RSA out_data;
+ TPM_RC rc = Tpm::ParseResponse_RSA_Encrypt(
+ response,
+ &out_data,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_data);
+}
+
+void Tpm::RSA_Encrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ AuthorizationDelegate* authorization_delegate,
+ const RSA_EncryptResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(RSA_EncryptErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(RSA_EncryptResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_RSA_Encrypt(
+ key_handle,
+ key_handle_name,
+ message,
+ in_scheme,
+ label,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::RSA_EncryptSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ TPM2B_PUBLIC_KEY_RSA* out_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_RSA_Encrypt(
+ key_handle,
+ key_handle_name,
+ message,
+ in_scheme,
+ label,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_RSA_Encrypt(
+ response,
+ out_data,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_RSA_Decrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_RSA_Decrypt;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string cipher_text_bytes;
+ rc = Serialize_TPM2B_PUBLIC_KEY_RSA(
+ cipher_text,
+ &cipher_text_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_RSA_DECRYPT(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string label_bytes;
+ rc = Serialize_TPM2B_DATA(
+ label,
+ &label_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = cipher_text_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ cipher_text_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(cipher_text_bytes.data(),
+ cipher_text_bytes.size());
+ parameter_section_bytes += cipher_text_bytes;
+ command_size += cipher_text_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(label_bytes.data(),
+ label_bytes.size());
+ parameter_section_bytes += label_bytes;
+ command_size += label_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_RSA_Decrypt(
+ const std::string& response,
+ TPM2B_PUBLIC_KEY_RSA* message,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_RSA_Decrypt;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string message_bytes;
+ rc = Parse_TPM2B_PUBLIC_KEY_RSA(
+ &buffer,
+ message,
+ &message_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = message_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ message_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PUBLIC_KEY_RSA(
+ &message_bytes,
+ message,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void RSA_DecryptErrorCallback(
+ const Tpm::RSA_DecryptResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_PUBLIC_KEY_RSA());
+}
+
+void RSA_DecryptResponseParser(
+ const Tpm::RSA_DecryptResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(RSA_DecryptErrorCallback, callback);
+ TPM2B_PUBLIC_KEY_RSA message;
+ TPM_RC rc = Tpm::ParseResponse_RSA_Decrypt(
+ response,
+ &message,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ message);
+}
+
+void Tpm::RSA_Decrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ AuthorizationDelegate* authorization_delegate,
+ const RSA_DecryptResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(RSA_DecryptErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(RSA_DecryptResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_RSA_Decrypt(
+ key_handle,
+ key_handle_name,
+ cipher_text,
+ in_scheme,
+ label,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::RSA_DecryptSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ TPM2B_PUBLIC_KEY_RSA* message,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_RSA_Decrypt(
+ key_handle,
+ key_handle_name,
+ cipher_text,
+ in_scheme,
+ label,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_RSA_Decrypt(
+ response,
+ message,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ECDH_KeyGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ECDH_KeyGen;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ECDH_KeyGen(
+ const std::string& response,
+ TPM2B_ECC_POINT* z_point,
+ TPM2B_ECC_POINT* pub_point,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ECDH_KeyGen;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string z_point_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ z_point,
+ &z_point_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pub_point_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ pub_point,
+ &pub_point_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = z_point_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ z_point_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ECC_POINT(
+ &z_point_bytes,
+ z_point,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ECDH_KeyGenErrorCallback(
+ const Tpm::ECDH_KeyGenResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ECC_POINT(),
+ TPM2B_ECC_POINT());
+}
+
+void ECDH_KeyGenResponseParser(
+ const Tpm::ECDH_KeyGenResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ECDH_KeyGenErrorCallback, callback);
+ TPM2B_ECC_POINT z_point;
+ TPM2B_ECC_POINT pub_point;
+ TPM_RC rc = Tpm::ParseResponse_ECDH_KeyGen(
+ response,
+ &z_point,
+ &pub_point,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ z_point,
+ pub_point);
+}
+
+void Tpm::ECDH_KeyGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ECDH_KeyGenResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ECDH_KeyGenErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ECDH_KeyGenResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ECDH_KeyGen(
+ key_handle,
+ key_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ECDH_KeyGenSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ TPM2B_ECC_POINT* z_point,
+ TPM2B_ECC_POINT* pub_point,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ECDH_KeyGen(
+ key_handle,
+ key_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ECDH_KeyGen(
+ response,
+ z_point,
+ pub_point,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ECDH_ZGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ECDH_ZGen;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_point_bytes;
+ rc = Serialize_TPM2B_ECC_POINT(
+ in_point,
+ &in_point_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_point_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_point_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(in_point_bytes.data(),
+ in_point_bytes.size());
+ parameter_section_bytes += in_point_bytes;
+ command_size += in_point_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ECDH_ZGen(
+ const std::string& response,
+ TPM2B_ECC_POINT* out_point,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ECDH_ZGen;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_point_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ out_point,
+ &out_point_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_point_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_point_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ECC_POINT(
+ &out_point_bytes,
+ out_point,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ECDH_ZGenErrorCallback(
+ const Tpm::ECDH_ZGenResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ECC_POINT());
+}
+
+void ECDH_ZGenResponseParser(
+ const Tpm::ECDH_ZGenResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ECDH_ZGenErrorCallback, callback);
+ TPM2B_ECC_POINT out_point;
+ TPM_RC rc = Tpm::ParseResponse_ECDH_ZGen(
+ response,
+ &out_point,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_point);
+}
+
+void Tpm::ECDH_ZGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ AuthorizationDelegate* authorization_delegate,
+ const ECDH_ZGenResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ECDH_ZGenErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ECDH_ZGenResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ECDH_ZGen(
+ key_handle,
+ key_handle_name,
+ in_point,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ECDH_ZGenSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ TPM2B_ECC_POINT* out_point,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ECDH_ZGen(
+ key_handle,
+ key_handle_name,
+ in_point,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ECDH_ZGen(
+ response,
+ out_point,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ECC_Parameters(
+ const TPMI_ECC_CURVE& curve_id,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ECC_Parameters;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string curve_id_bytes;
+ rc = Serialize_TPMI_ECC_CURVE(
+ curve_id,
+ &curve_id_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(curve_id_bytes.data(),
+ curve_id_bytes.size());
+ parameter_section_bytes += curve_id_bytes;
+ command_size += curve_id_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ECC_Parameters(
+ const std::string& response,
+ TPMS_ALGORITHM_DETAIL_ECC* parameters,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ECC_Parameters;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string parameters_bytes;
+ rc = Parse_TPMS_ALGORITHM_DETAIL_ECC(
+ &buffer,
+ parameters,
+ &parameters_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ECC_ParametersErrorCallback(
+ const Tpm::ECC_ParametersResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMS_ALGORITHM_DETAIL_ECC());
+}
+
+void ECC_ParametersResponseParser(
+ const Tpm::ECC_ParametersResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ECC_ParametersErrorCallback, callback);
+ TPMS_ALGORITHM_DETAIL_ECC parameters;
+ TPM_RC rc = Tpm::ParseResponse_ECC_Parameters(
+ response,
+ &parameters,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ parameters);
+}
+
+void Tpm::ECC_Parameters(
+ const TPMI_ECC_CURVE& curve_id,
+ AuthorizationDelegate* authorization_delegate,
+ const ECC_ParametersResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ECC_ParametersErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ECC_ParametersResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ECC_Parameters(
+ curve_id,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ECC_ParametersSync(
+ const TPMI_ECC_CURVE& curve_id,
+ TPMS_ALGORITHM_DETAIL_ECC* parameters,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ECC_Parameters(
+ curve_id,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ECC_Parameters(
+ response,
+ parameters,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ZGen_2Phase(
+ const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ZGen_2Phase;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_a_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_a,
+ &key_a_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_qs_b_bytes;
+ rc = Serialize_TPM2B_ECC_POINT(
+ in_qs_b,
+ &in_qs_b_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_qe_b_bytes;
+ rc = Serialize_TPM2B_ECC_POINT(
+ in_qe_b,
+ &in_qe_b_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMI_ECC_KEY_EXCHANGE(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string counter_bytes;
+ rc = Serialize_UINT16(
+ counter,
+ &counter_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_qs_b_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_qs_b_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_a_name.data(),
+ key_a_name.size());
+ handle_section_bytes += key_a_bytes;
+ command_size += key_a_bytes.size();
+ hash->Update(in_qs_b_bytes.data(),
+ in_qs_b_bytes.size());
+ parameter_section_bytes += in_qs_b_bytes;
+ command_size += in_qs_b_bytes.size();
+ hash->Update(in_qe_b_bytes.data(),
+ in_qe_b_bytes.size());
+ parameter_section_bytes += in_qe_b_bytes;
+ command_size += in_qe_b_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(counter_bytes.data(),
+ counter_bytes.size());
+ parameter_section_bytes += counter_bytes;
+ command_size += counter_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ZGen_2Phase(
+ const std::string& response,
+ TPM2B_ECC_POINT* out_z1,
+ TPM2B_ECC_POINT* out_z2,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ZGen_2Phase;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_z1_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ out_z1,
+ &out_z1_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string out_z2_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ out_z2,
+ &out_z2_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_z1_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_z1_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ECC_POINT(
+ &out_z1_bytes,
+ out_z1,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ZGen_2PhaseErrorCallback(
+ const Tpm::ZGen_2PhaseResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ECC_POINT(),
+ TPM2B_ECC_POINT());
+}
+
+void ZGen_2PhaseResponseParser(
+ const Tpm::ZGen_2PhaseResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ZGen_2PhaseErrorCallback, callback);
+ TPM2B_ECC_POINT out_z1;
+ TPM2B_ECC_POINT out_z2;
+ TPM_RC rc = Tpm::ParseResponse_ZGen_2Phase(
+ response,
+ &out_z1,
+ &out_z2,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_z1,
+ out_z2);
+}
+
+void Tpm::ZGen_2Phase(
+ const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ AuthorizationDelegate* authorization_delegate,
+ const ZGen_2PhaseResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ZGen_2PhaseErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ZGen_2PhaseResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ZGen_2Phase(
+ key_a,
+ key_a_name,
+ in_qs_b,
+ in_qe_b,
+ in_scheme,
+ counter,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ZGen_2PhaseSync(
+ const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ TPM2B_ECC_POINT* out_z1,
+ TPM2B_ECC_POINT* out_z2,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ZGen_2Phase(
+ key_a,
+ key_a_name,
+ in_qs_b,
+ in_qe_b,
+ in_scheme,
+ counter,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ZGen_2Phase(
+ response,
+ out_z1,
+ out_z2,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_EncryptDecrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_EncryptDecrypt;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string decrypt_bytes;
+ rc = Serialize_TPMI_YES_NO(
+ decrypt,
+ &decrypt_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string mode_bytes;
+ rc = Serialize_TPMI_ALG_SYM_MODE(
+ mode,
+ &mode_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string iv_in_bytes;
+ rc = Serialize_TPM2B_IV(
+ iv_in,
+ &iv_in_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_data_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ in_data,
+ &in_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(decrypt_bytes.data(),
+ decrypt_bytes.size());
+ parameter_section_bytes += decrypt_bytes;
+ command_size += decrypt_bytes.size();
+ hash->Update(mode_bytes.data(),
+ mode_bytes.size());
+ parameter_section_bytes += mode_bytes;
+ command_size += mode_bytes.size();
+ hash->Update(iv_in_bytes.data(),
+ iv_in_bytes.size());
+ parameter_section_bytes += iv_in_bytes;
+ command_size += iv_in_bytes.size();
+ hash->Update(in_data_bytes.data(),
+ in_data_bytes.size());
+ parameter_section_bytes += in_data_bytes;
+ command_size += in_data_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_EncryptDecrypt(
+ const std::string& response,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM2B_IV* iv_out,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_EncryptDecrypt;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_data_bytes;
+ rc = Parse_TPM2B_MAX_BUFFER(
+ &buffer,
+ out_data,
+ &out_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string iv_out_bytes;
+ rc = Parse_TPM2B_IV(
+ &buffer,
+ iv_out,
+ &iv_out_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_data_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_data_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_MAX_BUFFER(
+ &out_data_bytes,
+ out_data,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void EncryptDecryptErrorCallback(
+ const Tpm::EncryptDecryptResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_MAX_BUFFER(),
+ TPM2B_IV());
+}
+
+void EncryptDecryptResponseParser(
+ const Tpm::EncryptDecryptResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EncryptDecryptErrorCallback, callback);
+ TPM2B_MAX_BUFFER out_data;
+ TPM2B_IV iv_out;
+ TPM_RC rc = Tpm::ParseResponse_EncryptDecrypt(
+ response,
+ &out_data,
+ &iv_out,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_data,
+ iv_out);
+}
+
+void Tpm::EncryptDecrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ AuthorizationDelegate* authorization_delegate,
+ const EncryptDecryptResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EncryptDecryptErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(EncryptDecryptResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_EncryptDecrypt(
+ key_handle,
+ key_handle_name,
+ decrypt,
+ mode,
+ iv_in,
+ in_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::EncryptDecryptSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM2B_IV* iv_out,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_EncryptDecrypt(
+ key_handle,
+ key_handle_name,
+ decrypt,
+ mode,
+ iv_in,
+ in_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_EncryptDecrypt(
+ response,
+ out_data,
+ iv_out,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Hash(
+ const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Hash;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string data_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ data,
+ &data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hash_alg_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ hash_alg,
+ &hash_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hierarchy_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY(
+ hierarchy,
+ &hierarchy_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(data_bytes.data(),
+ data_bytes.size());
+ parameter_section_bytes += data_bytes;
+ command_size += data_bytes.size();
+ hash->Update(hash_alg_bytes.data(),
+ hash_alg_bytes.size());
+ parameter_section_bytes += hash_alg_bytes;
+ command_size += hash_alg_bytes.size();
+ hash->Update(hierarchy_bytes.data(),
+ hierarchy_bytes.size());
+ parameter_section_bytes += hierarchy_bytes;
+ command_size += hierarchy_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Hash(
+ const std::string& response,
+ TPM2B_DIGEST* out_hash,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Hash;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_hash_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ out_hash,
+ &out_hash_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string validation_bytes;
+ rc = Parse_TPMT_TK_HASHCHECK(
+ &buffer,
+ validation,
+ &validation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_hash_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_hash_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DIGEST(
+ &out_hash_bytes,
+ out_hash,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void HashErrorCallback(
+ const Tpm::HashResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DIGEST(),
+ TPMT_TK_HASHCHECK());
+}
+
+void HashResponseParser(
+ const Tpm::HashResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HashErrorCallback, callback);
+ TPM2B_DIGEST out_hash;
+ TPMT_TK_HASHCHECK validation;
+ TPM_RC rc = Tpm::ParseResponse_Hash(
+ response,
+ &out_hash,
+ &validation,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_hash,
+ validation);
+}
+
+void Tpm::Hash(
+ const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const HashResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HashErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(HashResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Hash(
+ data,
+ hash_alg,
+ hierarchy,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::HashSync(
+ const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM2B_DIGEST* out_hash,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Hash(
+ data,
+ hash_alg,
+ hierarchy,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Hash(
+ response,
+ out_hash,
+ validation,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_HMAC(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_HMAC;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ handle,
+ &handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string buffer_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ buffer,
+ &buffer_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hash_alg_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ hash_alg,
+ &hash_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = buffer_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ buffer_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(handle_name.data(),
+ handle_name.size());
+ handle_section_bytes += handle_bytes;
+ command_size += handle_bytes.size();
+ hash->Update(buffer_bytes.data(),
+ buffer_bytes.size());
+ parameter_section_bytes += buffer_bytes;
+ command_size += buffer_bytes.size();
+ hash->Update(hash_alg_bytes.data(),
+ hash_alg_bytes.size());
+ parameter_section_bytes += hash_alg_bytes;
+ command_size += hash_alg_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_HMAC(
+ const std::string& response,
+ TPM2B_DIGEST* out_hmac,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_HMAC;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_hmac_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ out_hmac,
+ &out_hmac_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_hmac_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_hmac_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DIGEST(
+ &out_hmac_bytes,
+ out_hmac,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void HMACErrorCallback(
+ const Tpm::HMACResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DIGEST());
+}
+
+void HMACResponseParser(
+ const Tpm::HMACResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HMACErrorCallback, callback);
+ TPM2B_DIGEST out_hmac;
+ TPM_RC rc = Tpm::ParseResponse_HMAC(
+ response,
+ &out_hmac,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ out_hmac);
+}
+
+void Tpm::HMAC(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HMACResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HMACErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(HMACResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_HMAC(
+ handle,
+ handle_name,
+ buffer,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::HMACSync(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ TPM2B_DIGEST* out_hmac,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_HMAC(
+ handle,
+ handle_name,
+ buffer,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_HMAC(
+ response,
+ out_hmac,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_GetRandom(
+ const UINT16& bytes_requested,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_GetRandom;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string bytes_requested_bytes;
+ rc = Serialize_UINT16(
+ bytes_requested,
+ &bytes_requested_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(bytes_requested_bytes.data(),
+ bytes_requested_bytes.size());
+ parameter_section_bytes += bytes_requested_bytes;
+ command_size += bytes_requested_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_GetRandom(
+ const std::string& response,
+ TPM2B_DIGEST* random_bytes,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_GetRandom;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string random_bytes_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ random_bytes,
+ &random_bytes_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = random_bytes_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ random_bytes_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DIGEST(
+ &random_bytes_bytes,
+ random_bytes,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void GetRandomErrorCallback(
+ const Tpm::GetRandomResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DIGEST());
+}
+
+void GetRandomResponseParser(
+ const Tpm::GetRandomResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetRandomErrorCallback, callback);
+ TPM2B_DIGEST random_bytes;
+ TPM_RC rc = Tpm::ParseResponse_GetRandom(
+ response,
+ &random_bytes,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ random_bytes);
+}
+
+void Tpm::GetRandom(
+ const UINT16& bytes_requested,
+ AuthorizationDelegate* authorization_delegate,
+ const GetRandomResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetRandomErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(GetRandomResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetRandom(
+ bytes_requested,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::GetRandomSync(
+ const UINT16& bytes_requested,
+ TPM2B_DIGEST* random_bytes,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetRandom(
+ bytes_requested,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_GetRandom(
+ response,
+ random_bytes,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_StirRandom(
+ const TPM2B_SENSITIVE_DATA& in_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_StirRandom;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_data_bytes;
+ rc = Serialize_TPM2B_SENSITIVE_DATA(
+ in_data,
+ &in_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(in_data_bytes.data(),
+ in_data_bytes.size());
+ parameter_section_bytes += in_data_bytes;
+ command_size += in_data_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_StirRandom(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_StirRandom;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void StirRandomErrorCallback(
+ const Tpm::StirRandomResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void StirRandomResponseParser(
+ const Tpm::StirRandomResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(StirRandomErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_StirRandom(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::StirRandom(
+ const TPM2B_SENSITIVE_DATA& in_data,
+ AuthorizationDelegate* authorization_delegate,
+ const StirRandomResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(StirRandomErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(StirRandomResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_StirRandom(
+ in_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::StirRandomSync(
+ const TPM2B_SENSITIVE_DATA& in_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_StirRandom(
+ in_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_StirRandom(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_HMAC_Start(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_HMAC_Start;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ handle,
+ &handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPM2B_AUTH(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hash_alg_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ hash_alg,
+ &hash_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(handle_name.data(),
+ handle_name.size());
+ handle_section_bytes += handle_bytes;
+ command_size += handle_bytes.size();
+ hash->Update(auth_bytes.data(),
+ auth_bytes.size());
+ parameter_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(hash_alg_bytes.data(),
+ hash_alg_bytes.size());
+ parameter_section_bytes += hash_alg_bytes;
+ command_size += hash_alg_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_HMAC_Start(
+ const std::string& response,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string sequence_handle_bytes;
+ rc = Parse_TPMI_DH_OBJECT(
+ &buffer,
+ sequence_handle,
+ &sequence_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_HMAC_Start;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void HMAC_StartErrorCallback(
+ const Tpm::HMAC_StartResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMI_DH_OBJECT());
+}
+
+void HMAC_StartResponseParser(
+ const Tpm::HMAC_StartResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HMAC_StartErrorCallback, callback);
+ TPMI_DH_OBJECT sequence_handle;
+ TPM_RC rc = Tpm::ParseResponse_HMAC_Start(
+ response,
+ &sequence_handle,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ sequence_handle);
+}
+
+void Tpm::HMAC_Start(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HMAC_StartResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HMAC_StartErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(HMAC_StartResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_HMAC_Start(
+ handle,
+ handle_name,
+ auth,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::HMAC_StartSync(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_HMAC_Start(
+ handle,
+ handle_name,
+ auth,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_HMAC_Start(
+ response,
+ sequence_handle,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_HashSequenceStart(
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_HashSequenceStart;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPM2B_AUTH(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hash_alg_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ hash_alg,
+ &hash_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_bytes.data(),
+ auth_bytes.size());
+ parameter_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(hash_alg_bytes.data(),
+ hash_alg_bytes.size());
+ parameter_section_bytes += hash_alg_bytes;
+ command_size += hash_alg_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_HashSequenceStart(
+ const std::string& response,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string sequence_handle_bytes;
+ rc = Parse_TPMI_DH_OBJECT(
+ &buffer,
+ sequence_handle,
+ &sequence_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_HashSequenceStart;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void HashSequenceStartErrorCallback(
+ const Tpm::HashSequenceStartResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMI_DH_OBJECT());
+}
+
+void HashSequenceStartResponseParser(
+ const Tpm::HashSequenceStartResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HashSequenceStartErrorCallback, callback);
+ TPMI_DH_OBJECT sequence_handle;
+ TPM_RC rc = Tpm::ParseResponse_HashSequenceStart(
+ response,
+ &sequence_handle,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ sequence_handle);
+}
+
+void Tpm::HashSequenceStart(
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HashSequenceStartResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HashSequenceStartErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(HashSequenceStartResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_HashSequenceStart(
+ auth,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::HashSequenceStartSync(
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_HashSequenceStart(
+ auth,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_HashSequenceStart(
+ response,
+ sequence_handle,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_SequenceUpdate(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_SequenceUpdate;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sequence_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sequence_handle,
+ &sequence_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string buffer_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ buffer,
+ &buffer_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = buffer_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ buffer_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sequence_handle_name.data(),
+ sequence_handle_name.size());
+ handle_section_bytes += sequence_handle_bytes;
+ command_size += sequence_handle_bytes.size();
+ hash->Update(buffer_bytes.data(),
+ buffer_bytes.size());
+ parameter_section_bytes += buffer_bytes;
+ command_size += buffer_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_SequenceUpdate(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_SequenceUpdate;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SequenceUpdateErrorCallback(
+ const Tpm::SequenceUpdateResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void SequenceUpdateResponseParser(
+ const Tpm::SequenceUpdateResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SequenceUpdateErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_SequenceUpdate(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::SequenceUpdate(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate,
+ const SequenceUpdateResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SequenceUpdateErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SequenceUpdateResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_SequenceUpdate(
+ sequence_handle,
+ sequence_handle_name,
+ buffer,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SequenceUpdateSync(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_SequenceUpdate(
+ sequence_handle,
+ sequence_handle_name,
+ buffer,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_SequenceUpdate(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_SequenceComplete(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_SequenceComplete;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sequence_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sequence_handle,
+ &sequence_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string buffer_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ buffer,
+ &buffer_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hierarchy_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY(
+ hierarchy,
+ &hierarchy_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = buffer_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ buffer_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sequence_handle_name.data(),
+ sequence_handle_name.size());
+ handle_section_bytes += sequence_handle_bytes;
+ command_size += sequence_handle_bytes.size();
+ hash->Update(buffer_bytes.data(),
+ buffer_bytes.size());
+ parameter_section_bytes += buffer_bytes;
+ command_size += buffer_bytes.size();
+ hash->Update(hierarchy_bytes.data(),
+ hierarchy_bytes.size());
+ parameter_section_bytes += hierarchy_bytes;
+ command_size += hierarchy_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_SequenceComplete(
+ const std::string& response,
+ TPM2B_DIGEST* result,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_SequenceComplete;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string result_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ result,
+ &result_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string validation_bytes;
+ rc = Parse_TPMT_TK_HASHCHECK(
+ &buffer,
+ validation,
+ &validation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = result_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ result_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DIGEST(
+ &result_bytes,
+ result,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SequenceCompleteErrorCallback(
+ const Tpm::SequenceCompleteResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DIGEST(),
+ TPMT_TK_HASHCHECK());
+}
+
+void SequenceCompleteResponseParser(
+ const Tpm::SequenceCompleteResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SequenceCompleteErrorCallback, callback);
+ TPM2B_DIGEST result;
+ TPMT_TK_HASHCHECK validation;
+ TPM_RC rc = Tpm::ParseResponse_SequenceComplete(
+ response,
+ &result,
+ &validation,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ result,
+ validation);
+}
+
+void Tpm::SequenceComplete(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const SequenceCompleteResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SequenceCompleteErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SequenceCompleteResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_SequenceComplete(
+ sequence_handle,
+ sequence_handle_name,
+ buffer,
+ hierarchy,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SequenceCompleteSync(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM2B_DIGEST* result,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_SequenceComplete(
+ sequence_handle,
+ sequence_handle_name,
+ buffer,
+ hierarchy,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_SequenceComplete(
+ response,
+ result,
+ validation,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_EventSequenceComplete(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_EventSequenceComplete;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_handle_bytes;
+ rc = Serialize_TPMI_DH_PCR(
+ pcr_handle,
+ &pcr_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sequence_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sequence_handle,
+ &sequence_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string buffer_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ buffer,
+ &buffer_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = buffer_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ buffer_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(pcr_handle_name.data(),
+ pcr_handle_name.size());
+ handle_section_bytes += pcr_handle_bytes;
+ command_size += pcr_handle_bytes.size();
+ hash->Update(sequence_handle_name.data(),
+ sequence_handle_name.size());
+ handle_section_bytes += sequence_handle_bytes;
+ command_size += sequence_handle_bytes.size();
+ hash->Update(buffer_bytes.data(),
+ buffer_bytes.size());
+ parameter_section_bytes += buffer_bytes;
+ command_size += buffer_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_EventSequenceComplete(
+ const std::string& response,
+ TPML_DIGEST_VALUES* results,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_EventSequenceComplete;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string results_bytes;
+ rc = Parse_TPML_DIGEST_VALUES(
+ &buffer,
+ results,
+ &results_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void EventSequenceCompleteErrorCallback(
+ const Tpm::EventSequenceCompleteResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPML_DIGEST_VALUES());
+}
+
+void EventSequenceCompleteResponseParser(
+ const Tpm::EventSequenceCompleteResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EventSequenceCompleteErrorCallback, callback);
+ TPML_DIGEST_VALUES results;
+ TPM_RC rc = Tpm::ParseResponse_EventSequenceComplete(
+ response,
+ &results,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ results);
+}
+
+void Tpm::EventSequenceComplete(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate,
+ const EventSequenceCompleteResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EventSequenceCompleteErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(EventSequenceCompleteResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_EventSequenceComplete(
+ pcr_handle,
+ pcr_handle_name,
+ sequence_handle,
+ sequence_handle_name,
+ buffer,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::EventSequenceCompleteSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ TPML_DIGEST_VALUES* results,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_EventSequenceComplete(
+ pcr_handle,
+ pcr_handle_name,
+ sequence_handle,
+ sequence_handle_name,
+ buffer,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_EventSequenceComplete(
+ response,
+ results,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Certify(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Certify;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(object_handle_name.data(),
+ object_handle_name.size());
+ handle_section_bytes += object_handle_bytes;
+ command_size += object_handle_bytes.size();
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Certify(
+ const std::string& response,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Certify;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string certify_info_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ certify_info,
+ &certify_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = certify_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ certify_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &certify_info_bytes,
+ certify_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void CertifyErrorCallback(
+ const Tpm::CertifyResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void CertifyResponseParser(
+ const Tpm::CertifyResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CertifyErrorCallback, callback);
+ TPM2B_ATTEST certify_info;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_Certify(
+ response,
+ &certify_info,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ certify_info,
+ signature);
+}
+
+void Tpm::Certify(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const CertifyResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CertifyErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(CertifyResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Certify(
+ object_handle,
+ object_handle_name,
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::CertifySync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Certify(
+ object_handle,
+ object_handle_name,
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Certify(
+ response,
+ certify_info,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_CertifyCreation(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_CertifyCreation;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_hash_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ creation_hash,
+ &creation_hash_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_ticket_bytes;
+ rc = Serialize_TPMT_TK_CREATION(
+ creation_ticket,
+ &creation_ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(object_handle_name.data(),
+ object_handle_name.size());
+ handle_section_bytes += object_handle_bytes;
+ command_size += object_handle_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(creation_hash_bytes.data(),
+ creation_hash_bytes.size());
+ parameter_section_bytes += creation_hash_bytes;
+ command_size += creation_hash_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(creation_ticket_bytes.data(),
+ creation_ticket_bytes.size());
+ parameter_section_bytes += creation_ticket_bytes;
+ command_size += creation_ticket_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_CertifyCreation(
+ const std::string& response,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_CertifyCreation;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string certify_info_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ certify_info,
+ &certify_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = certify_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ certify_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &certify_info_bytes,
+ certify_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void CertifyCreationErrorCallback(
+ const Tpm::CertifyCreationResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void CertifyCreationResponseParser(
+ const Tpm::CertifyCreationResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CertifyCreationErrorCallback, callback);
+ TPM2B_ATTEST certify_info;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_CertifyCreation(
+ response,
+ &certify_info,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ certify_info,
+ signature);
+}
+
+void Tpm::CertifyCreation(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const CertifyCreationResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CertifyCreationErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(CertifyCreationResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_CertifyCreation(
+ sign_handle,
+ sign_handle_name,
+ object_handle,
+ object_handle_name,
+ qualifying_data,
+ creation_hash,
+ in_scheme,
+ creation_ticket,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::CertifyCreationSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_CertifyCreation(
+ sign_handle,
+ sign_handle_name,
+ object_handle,
+ object_handle_name,
+ qualifying_data,
+ creation_hash,
+ in_scheme,
+ creation_ticket,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_CertifyCreation(
+ response,
+ certify_info,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Quote(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Quote;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcrselect_bytes;
+ rc = Serialize_TPML_PCR_SELECTION(
+ pcrselect,
+ &pcrselect_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(pcrselect_bytes.data(),
+ pcrselect_bytes.size());
+ parameter_section_bytes += pcrselect_bytes;
+ command_size += pcrselect_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Quote(
+ const std::string& response,
+ TPM2B_ATTEST* quoted,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Quote;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string quoted_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ quoted,
+ &quoted_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = quoted_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ quoted_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &quoted_bytes,
+ quoted,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void QuoteErrorCallback(
+ const Tpm::QuoteResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void QuoteResponseParser(
+ const Tpm::QuoteResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(QuoteErrorCallback, callback);
+ TPM2B_ATTEST quoted;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_Quote(
+ response,
+ &quoted,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ quoted,
+ signature);
+}
+
+void Tpm::Quote(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ AuthorizationDelegate* authorization_delegate,
+ const QuoteResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(QuoteErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(QuoteResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Quote(
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ pcrselect,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::QuoteSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ TPM2B_ATTEST* quoted,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Quote(
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ pcrselect,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Quote(
+ response,
+ quoted,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_GetSessionAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_GetSessionAuditDigest;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string privacy_admin_handle_bytes;
+ rc = Serialize_TPMI_RH_ENDORSEMENT(
+ privacy_admin_handle,
+ &privacy_admin_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string session_handle_bytes;
+ rc = Serialize_TPMI_SH_HMAC(
+ session_handle,
+ &session_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(privacy_admin_handle_name.data(),
+ privacy_admin_handle_name.size());
+ handle_section_bytes += privacy_admin_handle_bytes;
+ command_size += privacy_admin_handle_bytes.size();
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(session_handle_name.data(),
+ session_handle_name.size());
+ handle_section_bytes += session_handle_bytes;
+ command_size += session_handle_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_GetSessionAuditDigest(
+ const std::string& response,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_GetSessionAuditDigest;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string audit_info_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ audit_info,
+ &audit_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = audit_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ audit_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &audit_info_bytes,
+ audit_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void GetSessionAuditDigestErrorCallback(
+ const Tpm::GetSessionAuditDigestResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void GetSessionAuditDigestResponseParser(
+ const Tpm::GetSessionAuditDigestResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetSessionAuditDigestErrorCallback, callback);
+ TPM2B_ATTEST audit_info;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_GetSessionAuditDigest(
+ response,
+ &audit_info,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ audit_info,
+ signature);
+}
+
+void Tpm::GetSessionAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetSessionAuditDigestResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetSessionAuditDigestErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(GetSessionAuditDigestResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetSessionAuditDigest(
+ privacy_admin_handle,
+ privacy_admin_handle_name,
+ sign_handle,
+ sign_handle_name,
+ session_handle,
+ session_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::GetSessionAuditDigestSync(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetSessionAuditDigest(
+ privacy_admin_handle,
+ privacy_admin_handle_name,
+ sign_handle,
+ sign_handle_name,
+ session_handle,
+ session_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_GetSessionAuditDigest(
+ response,
+ audit_info,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_GetCommandAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_GetCommandAuditDigest;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string privacy_handle_bytes;
+ rc = Serialize_TPMI_RH_ENDORSEMENT(
+ privacy_handle,
+ &privacy_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(privacy_handle_name.data(),
+ privacy_handle_name.size());
+ handle_section_bytes += privacy_handle_bytes;
+ command_size += privacy_handle_bytes.size();
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_GetCommandAuditDigest(
+ const std::string& response,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_GetCommandAuditDigest;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string audit_info_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ audit_info,
+ &audit_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = audit_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ audit_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &audit_info_bytes,
+ audit_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void GetCommandAuditDigestErrorCallback(
+ const Tpm::GetCommandAuditDigestResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void GetCommandAuditDigestResponseParser(
+ const Tpm::GetCommandAuditDigestResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetCommandAuditDigestErrorCallback, callback);
+ TPM2B_ATTEST audit_info;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_GetCommandAuditDigest(
+ response,
+ &audit_info,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ audit_info,
+ signature);
+}
+
+void Tpm::GetCommandAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetCommandAuditDigestResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetCommandAuditDigestErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(GetCommandAuditDigestResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetCommandAuditDigest(
+ privacy_handle,
+ privacy_handle_name,
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::GetCommandAuditDigestSync(
+ const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetCommandAuditDigest(
+ privacy_handle,
+ privacy_handle_name,
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_GetCommandAuditDigest(
+ response,
+ audit_info,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_GetTime(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_GetTime;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string privacy_admin_handle_bytes;
+ rc = Serialize_TPMI_RH_ENDORSEMENT(
+ privacy_admin_handle,
+ &privacy_admin_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(privacy_admin_handle_name.data(),
+ privacy_admin_handle_name.size());
+ handle_section_bytes += privacy_admin_handle_bytes;
+ command_size += privacy_admin_handle_bytes.size();
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_GetTime(
+ const std::string& response,
+ TPM2B_ATTEST* time_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_GetTime;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string time_info_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ time_info,
+ &time_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = time_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ time_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &time_info_bytes,
+ time_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void GetTimeErrorCallback(
+ const Tpm::GetTimeResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void GetTimeResponseParser(
+ const Tpm::GetTimeResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetTimeErrorCallback, callback);
+ TPM2B_ATTEST time_info;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_GetTime(
+ response,
+ &time_info,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ time_info,
+ signature);
+}
+
+void Tpm::GetTime(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetTimeResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetTimeErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(GetTimeResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetTime(
+ privacy_admin_handle,
+ privacy_admin_handle_name,
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::GetTimeSync(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* time_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetTime(
+ privacy_admin_handle,
+ privacy_admin_handle_name,
+ sign_handle,
+ sign_handle_name,
+ qualifying_data,
+ in_scheme,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_GetTime(
+ response,
+ time_info,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Commit(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Commit;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string param_size_bytes;
+ rc = Serialize_UINT32(
+ param_size,
+ &param_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string p1_bytes;
+ rc = Serialize_TPM2B_ECC_POINT(
+ p1,
+ &p1_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string s2_bytes;
+ rc = Serialize_TPM2B_SENSITIVE_DATA(
+ s2,
+ &s2_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string y2_bytes;
+ rc = Serialize_TPM2B_ECC_PARAMETER(
+ y2,
+ &y2_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(param_size_bytes.data(),
+ param_size_bytes.size());
+ parameter_section_bytes += param_size_bytes;
+ command_size += param_size_bytes.size();
+ hash->Update(p1_bytes.data(),
+ p1_bytes.size());
+ parameter_section_bytes += p1_bytes;
+ command_size += p1_bytes.size();
+ hash->Update(s2_bytes.data(),
+ s2_bytes.size());
+ parameter_section_bytes += s2_bytes;
+ command_size += s2_bytes.size();
+ hash->Update(y2_bytes.data(),
+ y2_bytes.size());
+ parameter_section_bytes += y2_bytes;
+ command_size += y2_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Commit(
+ const std::string& response,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Commit;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string param_size_out_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ param_size_out,
+ &param_size_out_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string k_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ k,
+ &k_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string l_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ l,
+ &l_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string e_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ e,
+ &e_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string counter_bytes;
+ rc = Parse_UINT16(
+ &buffer,
+ counter,
+ &counter_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void CommitErrorCallback(
+ const Tpm::CommitResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ UINT32(),
+ TPM2B_ECC_POINT(),
+ TPM2B_ECC_POINT(),
+ TPM2B_ECC_POINT(),
+ UINT16());
+}
+
+void CommitResponseParser(
+ const Tpm::CommitResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CommitErrorCallback, callback);
+ UINT32 param_size_out;
+ TPM2B_ECC_POINT k;
+ TPM2B_ECC_POINT l;
+ TPM2B_ECC_POINT e;
+ UINT16 counter;
+ TPM_RC rc = Tpm::ParseResponse_Commit(
+ response,
+ &param_size_out,
+ &k,
+ &l,
+ &e,
+ &counter,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ param_size_out,
+ k,
+ l,
+ e,
+ counter);
+}
+
+void Tpm::Commit(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ AuthorizationDelegate* authorization_delegate,
+ const CommitResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CommitErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(CommitResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Commit(
+ sign_handle,
+ sign_handle_name,
+ param_size,
+ p1,
+ s2,
+ y2,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::CommitSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Commit(
+ sign_handle,
+ sign_handle_name,
+ param_size,
+ p1,
+ s2,
+ y2,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Commit(
+ response,
+ param_size_out,
+ k,
+ l,
+ e,
+ counter,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_EC_Ephemeral(
+ const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_EC_Ephemeral;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string param_size_bytes;
+ rc = Serialize_UINT32(
+ param_size,
+ &param_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string curve_id_bytes;
+ rc = Serialize_TPMI_ECC_CURVE(
+ curve_id,
+ &curve_id_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(param_size_bytes.data(),
+ param_size_bytes.size());
+ parameter_section_bytes += param_size_bytes;
+ command_size += param_size_bytes.size();
+ hash->Update(curve_id_bytes.data(),
+ curve_id_bytes.size());
+ parameter_section_bytes += curve_id_bytes;
+ command_size += curve_id_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_EC_Ephemeral(
+ const std::string& response,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* q,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_EC_Ephemeral;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string param_size_out_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ param_size_out,
+ &param_size_out_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string q_bytes;
+ rc = Parse_TPM2B_ECC_POINT(
+ &buffer,
+ q,
+ &q_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string counter_bytes;
+ rc = Parse_UINT16(
+ &buffer,
+ counter,
+ &counter_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void EC_EphemeralErrorCallback(
+ const Tpm::EC_EphemeralResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ UINT32(),
+ TPM2B_ECC_POINT(),
+ UINT16());
+}
+
+void EC_EphemeralResponseParser(
+ const Tpm::EC_EphemeralResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EC_EphemeralErrorCallback, callback);
+ UINT32 param_size_out;
+ TPM2B_ECC_POINT q;
+ UINT16 counter;
+ TPM_RC rc = Tpm::ParseResponse_EC_Ephemeral(
+ response,
+ &param_size_out,
+ &q,
+ &counter,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ param_size_out,
+ q,
+ counter);
+}
+
+void Tpm::EC_Ephemeral(
+ const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ AuthorizationDelegate* authorization_delegate,
+ const EC_EphemeralResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EC_EphemeralErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(EC_EphemeralResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_EC_Ephemeral(
+ param_size,
+ curve_id,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::EC_EphemeralSync(
+ const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* q,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_EC_Ephemeral(
+ param_size,
+ curve_id,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_EC_Ephemeral(
+ response,
+ param_size_out,
+ q,
+ counter,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_VerifySignature(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_VerifySignature;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string digest_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ digest,
+ &digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Serialize_TPMT_SIGNATURE(
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = digest_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ digest_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(digest_bytes.data(),
+ digest_bytes.size());
+ parameter_section_bytes += digest_bytes;
+ command_size += digest_bytes.size();
+ hash->Update(signature_bytes.data(),
+ signature_bytes.size());
+ parameter_section_bytes += signature_bytes;
+ command_size += signature_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_VerifySignature(
+ const std::string& response,
+ TPMT_TK_VERIFIED* validation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_VerifySignature;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string validation_bytes;
+ rc = Parse_TPMT_TK_VERIFIED(
+ &buffer,
+ validation,
+ &validation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void VerifySignatureErrorCallback(
+ const Tpm::VerifySignatureResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMT_TK_VERIFIED());
+}
+
+void VerifySignatureResponseParser(
+ const Tpm::VerifySignatureResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(VerifySignatureErrorCallback, callback);
+ TPMT_TK_VERIFIED validation;
+ TPM_RC rc = Tpm::ParseResponse_VerifySignature(
+ response,
+ &validation,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ validation);
+}
+
+void Tpm::VerifySignature(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ AuthorizationDelegate* authorization_delegate,
+ const VerifySignatureResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(VerifySignatureErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(VerifySignatureResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_VerifySignature(
+ key_handle,
+ key_handle_name,
+ digest,
+ signature,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::VerifySignatureSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ TPMT_TK_VERIFIED* validation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_VerifySignature(
+ key_handle,
+ key_handle_name,
+ digest,
+ signature,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_VerifySignature(
+ response,
+ validation,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Sign(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Sign;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string digest_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ digest,
+ &digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string validation_bytes;
+ rc = Serialize_TPMT_TK_HASHCHECK(
+ validation,
+ &validation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = digest_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ digest_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(digest_bytes.data(),
+ digest_bytes.size());
+ parameter_section_bytes += digest_bytes;
+ command_size += digest_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(validation_bytes.data(),
+ validation_bytes.size());
+ parameter_section_bytes += validation_bytes;
+ command_size += validation_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Sign(
+ const std::string& response,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Sign;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SignErrorCallback(
+ const Tpm::SignResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMT_SIGNATURE());
+}
+
+void SignResponseParser(
+ const Tpm::SignResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SignErrorCallback, callback);
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_Sign(
+ response,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ signature);
+}
+
+void Tpm::Sign(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ AuthorizationDelegate* authorization_delegate,
+ const SignResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SignErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SignResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Sign(
+ key_handle,
+ key_handle_name,
+ digest,
+ in_scheme,
+ validation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SignSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Sign(
+ key_handle,
+ key_handle_name,
+ digest,
+ in_scheme,
+ validation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Sign(
+ response,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_SetCommandCodeAuditStatus(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_SetCommandCodeAuditStatus;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string audit_alg_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ audit_alg,
+ &audit_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string set_list_bytes;
+ rc = Serialize_TPML_CC(
+ set_list,
+ &set_list_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string clear_list_bytes;
+ rc = Serialize_TPML_CC(
+ clear_list,
+ &clear_list_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_name.data(),
+ auth_name.size());
+ handle_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(audit_alg_bytes.data(),
+ audit_alg_bytes.size());
+ parameter_section_bytes += audit_alg_bytes;
+ command_size += audit_alg_bytes.size();
+ hash->Update(set_list_bytes.data(),
+ set_list_bytes.size());
+ parameter_section_bytes += set_list_bytes;
+ command_size += set_list_bytes.size();
+ hash->Update(clear_list_bytes.data(),
+ clear_list_bytes.size());
+ parameter_section_bytes += clear_list_bytes;
+ command_size += clear_list_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_SetCommandCodeAuditStatus(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_SetCommandCodeAuditStatus;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SetCommandCodeAuditStatusErrorCallback(
+ const Tpm::SetCommandCodeAuditStatusResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void SetCommandCodeAuditStatusResponseParser(
+ const Tpm::SetCommandCodeAuditStatusResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SetCommandCodeAuditStatusErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_SetCommandCodeAuditStatus(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::SetCommandCodeAuditStatus(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate,
+ const SetCommandCodeAuditStatusResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SetCommandCodeAuditStatusErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SetCommandCodeAuditStatusResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_SetCommandCodeAuditStatus(
+ auth,
+ auth_name,
+ audit_alg,
+ set_list,
+ clear_list,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SetCommandCodeAuditStatusSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_SetCommandCodeAuditStatus(
+ auth,
+ auth_name,
+ audit_alg,
+ set_list,
+ clear_list,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_SetCommandCodeAuditStatus(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_Extend(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_Extend;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_handle_bytes;
+ rc = Serialize_TPMI_DH_PCR(
+ pcr_handle,
+ &pcr_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string digests_bytes;
+ rc = Serialize_TPML_DIGEST_VALUES(
+ digests,
+ &digests_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(pcr_handle_name.data(),
+ pcr_handle_name.size());
+ handle_section_bytes += pcr_handle_bytes;
+ command_size += pcr_handle_bytes.size();
+ hash->Update(digests_bytes.data(),
+ digests_bytes.size());
+ parameter_section_bytes += digests_bytes;
+ command_size += digests_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_Extend(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_Extend;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_ExtendErrorCallback(
+ const Tpm::PCR_ExtendResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PCR_ExtendResponseParser(
+ const Tpm::PCR_ExtendResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_ExtendErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PCR_Extend(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PCR_Extend(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ExtendResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_ExtendErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_ExtendResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Extend(
+ pcr_handle,
+ pcr_handle_name,
+ digests,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_ExtendSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Extend(
+ pcr_handle,
+ pcr_handle_name,
+ digests,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_Extend(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_Event(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_Event;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_handle_bytes;
+ rc = Serialize_TPMI_DH_PCR(
+ pcr_handle,
+ &pcr_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string event_data_bytes;
+ rc = Serialize_TPM2B_EVENT(
+ event_data,
+ &event_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = event_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ event_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(pcr_handle_name.data(),
+ pcr_handle_name.size());
+ handle_section_bytes += pcr_handle_bytes;
+ command_size += pcr_handle_bytes.size();
+ hash->Update(event_data_bytes.data(),
+ event_data_bytes.size());
+ parameter_section_bytes += event_data_bytes;
+ command_size += event_data_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_Event(
+ const std::string& response,
+ TPML_DIGEST_VALUES* digests,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_Event;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string digests_bytes;
+ rc = Parse_TPML_DIGEST_VALUES(
+ &buffer,
+ digests,
+ &digests_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_EventErrorCallback(
+ const Tpm::PCR_EventResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPML_DIGEST_VALUES());
+}
+
+void PCR_EventResponseParser(
+ const Tpm::PCR_EventResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_EventErrorCallback, callback);
+ TPML_DIGEST_VALUES digests;
+ TPM_RC rc = Tpm::ParseResponse_PCR_Event(
+ response,
+ &digests,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ digests);
+}
+
+void Tpm::PCR_Event(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_EventResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_EventErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_EventResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Event(
+ pcr_handle,
+ pcr_handle_name,
+ event_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_EventSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ TPML_DIGEST_VALUES* digests,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Event(
+ pcr_handle,
+ pcr_handle_name,
+ event_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_Event(
+ response,
+ digests,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_Read(
+ const TPML_PCR_SELECTION& pcr_selection_in,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_Read;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_selection_in_bytes;
+ rc = Serialize_TPML_PCR_SELECTION(
+ pcr_selection_in,
+ &pcr_selection_in_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(pcr_selection_in_bytes.data(),
+ pcr_selection_in_bytes.size());
+ parameter_section_bytes += pcr_selection_in_bytes;
+ command_size += pcr_selection_in_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_Read(
+ const std::string& response,
+ UINT32* pcr_update_counter,
+ TPML_PCR_SELECTION* pcr_selection_out,
+ TPML_DIGEST* pcr_values,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_Read;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string pcr_update_counter_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ pcr_update_counter,
+ &pcr_update_counter_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_selection_out_bytes;
+ rc = Parse_TPML_PCR_SELECTION(
+ &buffer,
+ pcr_selection_out,
+ &pcr_selection_out_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_values_bytes;
+ rc = Parse_TPML_DIGEST(
+ &buffer,
+ pcr_values,
+ &pcr_values_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_ReadErrorCallback(
+ const Tpm::PCR_ReadResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ UINT32(),
+ TPML_PCR_SELECTION(),
+ TPML_DIGEST());
+}
+
+void PCR_ReadResponseParser(
+ const Tpm::PCR_ReadResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_ReadErrorCallback, callback);
+ UINT32 pcr_update_counter;
+ TPML_PCR_SELECTION pcr_selection_out;
+ TPML_DIGEST pcr_values;
+ TPM_RC rc = Tpm::ParseResponse_PCR_Read(
+ response,
+ &pcr_update_counter,
+ &pcr_selection_out,
+ &pcr_values,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ pcr_update_counter,
+ pcr_selection_out,
+ pcr_values);
+}
+
+void Tpm::PCR_Read(
+ const TPML_PCR_SELECTION& pcr_selection_in,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ReadResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_ReadErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_ReadResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Read(
+ pcr_selection_in,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_ReadSync(
+ const TPML_PCR_SELECTION& pcr_selection_in,
+ UINT32* pcr_update_counter,
+ TPML_PCR_SELECTION* pcr_selection_out,
+ TPML_DIGEST* pcr_values,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Read(
+ pcr_selection_in,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_Read(
+ response,
+ pcr_update_counter,
+ pcr_selection_out,
+ pcr_values,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_Allocate(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_Allocate;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_allocation_bytes;
+ rc = Serialize_TPML_PCR_SELECTION(
+ pcr_allocation,
+ &pcr_allocation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(pcr_allocation_bytes.data(),
+ pcr_allocation_bytes.size());
+ parameter_section_bytes += pcr_allocation_bytes;
+ command_size += pcr_allocation_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_Allocate(
+ const std::string& response,
+ TPMI_YES_NO* allocation_success,
+ UINT32* max_pcr,
+ UINT32* size_needed,
+ UINT32* size_available,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_Allocate;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string allocation_success_bytes;
+ rc = Parse_TPMI_YES_NO(
+ &buffer,
+ allocation_success,
+ &allocation_success_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string max_pcr_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ max_pcr,
+ &max_pcr_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string size_needed_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ size_needed,
+ &size_needed_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string size_available_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ size_available,
+ &size_available_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_AllocateErrorCallback(
+ const Tpm::PCR_AllocateResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMI_YES_NO(),
+ UINT32(),
+ UINT32(),
+ UINT32());
+}
+
+void PCR_AllocateResponseParser(
+ const Tpm::PCR_AllocateResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_AllocateErrorCallback, callback);
+ TPMI_YES_NO allocation_success;
+ UINT32 max_pcr;
+ UINT32 size_needed;
+ UINT32 size_available;
+ TPM_RC rc = Tpm::ParseResponse_PCR_Allocate(
+ response,
+ &allocation_success,
+ &max_pcr,
+ &size_needed,
+ &size_available,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ allocation_success,
+ max_pcr,
+ size_needed,
+ size_available);
+}
+
+void Tpm::PCR_Allocate(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_AllocateResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_AllocateErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_AllocateResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Allocate(
+ auth_handle,
+ auth_handle_name,
+ pcr_allocation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_AllocateSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ TPMI_YES_NO* allocation_success,
+ UINT32* max_pcr,
+ UINT32* size_needed,
+ UINT32* size_available,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Allocate(
+ auth_handle,
+ auth_handle_name,
+ pcr_allocation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_Allocate(
+ response,
+ allocation_success,
+ max_pcr,
+ size_needed,
+ size_available,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_SetAuthPolicy(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_SetAuthPolicy;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_policy_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ auth_policy,
+ &auth_policy_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_digest_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ policy_digest,
+ &policy_digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_num_bytes;
+ rc = Serialize_TPMI_DH_PCR(
+ pcr_num,
+ &pcr_num_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = auth_policy_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ auth_policy_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(pcr_num_name.data(),
+ pcr_num_name.size());
+ handle_section_bytes += pcr_num_bytes;
+ command_size += pcr_num_bytes.size();
+ hash->Update(auth_policy_bytes.data(),
+ auth_policy_bytes.size());
+ parameter_section_bytes += auth_policy_bytes;
+ command_size += auth_policy_bytes.size();
+ hash->Update(policy_digest_bytes.data(),
+ policy_digest_bytes.size());
+ parameter_section_bytes += policy_digest_bytes;
+ command_size += policy_digest_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_SetAuthPolicy(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_SetAuthPolicy;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_SetAuthPolicyErrorCallback(
+ const Tpm::PCR_SetAuthPolicyResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PCR_SetAuthPolicyResponseParser(
+ const Tpm::PCR_SetAuthPolicyResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_SetAuthPolicyErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PCR_SetAuthPolicy(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PCR_SetAuthPolicy(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_SetAuthPolicyResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_SetAuthPolicyErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_SetAuthPolicyResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_SetAuthPolicy(
+ auth_handle,
+ auth_handle_name,
+ pcr_num,
+ pcr_num_name,
+ auth_policy,
+ policy_digest,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_SetAuthPolicySync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_SetAuthPolicy(
+ auth_handle,
+ auth_handle_name,
+ pcr_num,
+ pcr_num_name,
+ auth_policy,
+ policy_digest,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_SetAuthPolicy(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_SetAuthValue(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_SetAuthValue;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_handle_bytes;
+ rc = Serialize_TPMI_DH_PCR(
+ pcr_handle,
+ &pcr_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(pcr_handle_name.data(),
+ pcr_handle_name.size());
+ handle_section_bytes += pcr_handle_bytes;
+ command_size += pcr_handle_bytes.size();
+ hash->Update(auth_bytes.data(),
+ auth_bytes.size());
+ parameter_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_SetAuthValue(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_SetAuthValue;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_SetAuthValueErrorCallback(
+ const Tpm::PCR_SetAuthValueResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PCR_SetAuthValueResponseParser(
+ const Tpm::PCR_SetAuthValueResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_SetAuthValueErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PCR_SetAuthValue(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PCR_SetAuthValue(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_SetAuthValueResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_SetAuthValueErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_SetAuthValueResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_SetAuthValue(
+ pcr_handle,
+ pcr_handle_name,
+ auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_SetAuthValueSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_SetAuthValue(
+ pcr_handle,
+ pcr_handle_name,
+ auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_SetAuthValue(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PCR_Reset(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PCR_Reset;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_handle_bytes;
+ rc = Serialize_TPMI_DH_PCR(
+ pcr_handle,
+ &pcr_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(pcr_handle_name.data(),
+ pcr_handle_name.size());
+ handle_section_bytes += pcr_handle_bytes;
+ command_size += pcr_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PCR_Reset(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PCR_Reset;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PCR_ResetErrorCallback(
+ const Tpm::PCR_ResetResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PCR_ResetResponseParser(
+ const Tpm::PCR_ResetResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_ResetErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PCR_Reset(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PCR_Reset(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ResetResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PCR_ResetErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PCR_ResetResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Reset(
+ pcr_handle,
+ pcr_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PCR_ResetSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PCR_Reset(
+ pcr_handle,
+ pcr_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PCR_Reset(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicySigned(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicySigned;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_object_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ auth_object,
+ &auth_object_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nonce_tpm_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ nonce_tpm,
+ &nonce_tpm_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string cp_hash_a_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ cp_hash_a,
+ &cp_hash_a_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_ref_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ policy_ref,
+ &policy_ref_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string expiration_bytes;
+ rc = Serialize_INT32(
+ expiration,
+ &expiration_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMT_SIGNATURE(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = nonce_tpm_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ nonce_tpm_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_object_name.data(),
+ auth_object_name.size());
+ handle_section_bytes += auth_object_bytes;
+ command_size += auth_object_bytes.size();
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(nonce_tpm_bytes.data(),
+ nonce_tpm_bytes.size());
+ parameter_section_bytes += nonce_tpm_bytes;
+ command_size += nonce_tpm_bytes.size();
+ hash->Update(cp_hash_a_bytes.data(),
+ cp_hash_a_bytes.size());
+ parameter_section_bytes += cp_hash_a_bytes;
+ command_size += cp_hash_a_bytes.size();
+ hash->Update(policy_ref_bytes.data(),
+ policy_ref_bytes.size());
+ parameter_section_bytes += policy_ref_bytes;
+ command_size += policy_ref_bytes.size();
+ hash->Update(expiration_bytes.data(),
+ expiration_bytes.size());
+ parameter_section_bytes += expiration_bytes;
+ command_size += expiration_bytes.size();
+ hash->Update(auth_bytes.data(),
+ auth_bytes.size());
+ parameter_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicySigned(
+ const std::string& response,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicySigned;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string timeout_bytes;
+ rc = Parse_TPM2B_TIMEOUT(
+ &buffer,
+ timeout,
+ &timeout_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_ticket_bytes;
+ rc = Parse_TPMT_TK_AUTH(
+ &buffer,
+ policy_ticket,
+ &policy_ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = timeout_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ timeout_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_TIMEOUT(
+ &timeout_bytes,
+ timeout,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicySignedErrorCallback(
+ const Tpm::PolicySignedResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_TIMEOUT(),
+ TPMT_TK_AUTH());
+}
+
+void PolicySignedResponseParser(
+ const Tpm::PolicySignedResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicySignedErrorCallback, callback);
+ TPM2B_TIMEOUT timeout;
+ TPMT_TK_AUTH policy_ticket;
+ TPM_RC rc = Tpm::ParseResponse_PolicySigned(
+ response,
+ &timeout,
+ &policy_ticket,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ timeout,
+ policy_ticket);
+}
+
+void Tpm::PolicySigned(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySignedResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicySignedErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicySignedResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicySigned(
+ auth_object,
+ auth_object_name,
+ policy_session,
+ policy_session_name,
+ nonce_tpm,
+ cp_hash_a,
+ policy_ref,
+ expiration,
+ auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicySignedSync(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicySigned(
+ auth_object,
+ auth_object_name,
+ policy_session,
+ policy_session_name,
+ nonce_tpm,
+ cp_hash_a,
+ policy_ref,
+ expiration,
+ auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicySigned(
+ response,
+ timeout,
+ policy_ticket,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicySecret(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicySecret;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_DH_ENTITY(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nonce_tpm_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ nonce_tpm,
+ &nonce_tpm_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string cp_hash_a_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ cp_hash_a,
+ &cp_hash_a_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_ref_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ policy_ref,
+ &policy_ref_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string expiration_bytes;
+ rc = Serialize_INT32(
+ expiration,
+ &expiration_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = nonce_tpm_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ nonce_tpm_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(nonce_tpm_bytes.data(),
+ nonce_tpm_bytes.size());
+ parameter_section_bytes += nonce_tpm_bytes;
+ command_size += nonce_tpm_bytes.size();
+ hash->Update(cp_hash_a_bytes.data(),
+ cp_hash_a_bytes.size());
+ parameter_section_bytes += cp_hash_a_bytes;
+ command_size += cp_hash_a_bytes.size();
+ hash->Update(policy_ref_bytes.data(),
+ policy_ref_bytes.size());
+ parameter_section_bytes += policy_ref_bytes;
+ command_size += policy_ref_bytes.size();
+ hash->Update(expiration_bytes.data(),
+ expiration_bytes.size());
+ parameter_section_bytes += expiration_bytes;
+ command_size += expiration_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicySecret(
+ const std::string& response,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicySecret;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string timeout_bytes;
+ rc = Parse_TPM2B_TIMEOUT(
+ &buffer,
+ timeout,
+ &timeout_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_ticket_bytes;
+ rc = Parse_TPMT_TK_AUTH(
+ &buffer,
+ policy_ticket,
+ &policy_ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = timeout_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ timeout_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_TIMEOUT(
+ &timeout_bytes,
+ timeout,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicySecretErrorCallback(
+ const Tpm::PolicySecretResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_TIMEOUT(),
+ TPMT_TK_AUTH());
+}
+
+void PolicySecretResponseParser(
+ const Tpm::PolicySecretResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicySecretErrorCallback, callback);
+ TPM2B_TIMEOUT timeout;
+ TPMT_TK_AUTH policy_ticket;
+ TPM_RC rc = Tpm::ParseResponse_PolicySecret(
+ response,
+ &timeout,
+ &policy_ticket,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ timeout,
+ policy_ticket);
+}
+
+void Tpm::PolicySecret(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySecretResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicySecretErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicySecretResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicySecret(
+ auth_handle,
+ auth_handle_name,
+ policy_session,
+ policy_session_name,
+ nonce_tpm,
+ cp_hash_a,
+ policy_ref,
+ expiration,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicySecretSync(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicySecret(
+ auth_handle,
+ auth_handle_name,
+ policy_session,
+ policy_session_name,
+ nonce_tpm,
+ cp_hash_a,
+ policy_ref,
+ expiration,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicySecret(
+ response,
+ timeout,
+ policy_ticket,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyTicket(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyTicket;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string timeout_bytes;
+ rc = Serialize_TPM2B_TIMEOUT(
+ timeout,
+ &timeout_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string cp_hash_a_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ cp_hash_a,
+ &cp_hash_a_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_ref_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ policy_ref,
+ &policy_ref_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_name_bytes;
+ rc = Serialize_TPM2B_NAME(
+ auth_name,
+ &auth_name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string ticket_bytes;
+ rc = Serialize_TPMT_TK_AUTH(
+ ticket,
+ &ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = timeout_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ timeout_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(timeout_bytes.data(),
+ timeout_bytes.size());
+ parameter_section_bytes += timeout_bytes;
+ command_size += timeout_bytes.size();
+ hash->Update(cp_hash_a_bytes.data(),
+ cp_hash_a_bytes.size());
+ parameter_section_bytes += cp_hash_a_bytes;
+ command_size += cp_hash_a_bytes.size();
+ hash->Update(policy_ref_bytes.data(),
+ policy_ref_bytes.size());
+ parameter_section_bytes += policy_ref_bytes;
+ command_size += policy_ref_bytes.size();
+ hash->Update(auth_name_bytes.data(),
+ auth_name_bytes.size());
+ parameter_section_bytes += auth_name_bytes;
+ command_size += auth_name_bytes.size();
+ hash->Update(ticket_bytes.data(),
+ ticket_bytes.size());
+ parameter_section_bytes += ticket_bytes;
+ command_size += ticket_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyTicket(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyTicket;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyTicketErrorCallback(
+ const Tpm::PolicyTicketResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyTicketResponseParser(
+ const Tpm::PolicyTicketResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyTicketErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyTicket(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyTicket(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyTicketResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyTicketErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyTicketResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyTicket(
+ policy_session,
+ policy_session_name,
+ timeout,
+ cp_hash_a,
+ policy_ref,
+ auth_name,
+ ticket,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyTicketSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyTicket(
+ policy_session,
+ policy_session_name,
+ timeout,
+ cp_hash_a,
+ policy_ref,
+ auth_name,
+ ticket,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyTicket(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyOR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyOR;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string p_hash_list_bytes;
+ rc = Serialize_TPML_DIGEST(
+ p_hash_list,
+ &p_hash_list_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(p_hash_list_bytes.data(),
+ p_hash_list_bytes.size());
+ parameter_section_bytes += p_hash_list_bytes;
+ command_size += p_hash_list_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyOR(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyOR;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyORErrorCallback(
+ const Tpm::PolicyORResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyORResponseParser(
+ const Tpm::PolicyORResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyORErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyOR(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyOR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyORResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyORErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyORResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyOR(
+ policy_session,
+ policy_session_name,
+ p_hash_list,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyORSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyOR(
+ policy_session,
+ policy_session_name,
+ p_hash_list,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyOR(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyPCR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyPCR;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcr_digest_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ pcr_digest,
+ &pcr_digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string pcrs_bytes;
+ rc = Serialize_TPML_PCR_SELECTION(
+ pcrs,
+ &pcrs_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = pcr_digest_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ pcr_digest_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(pcr_digest_bytes.data(),
+ pcr_digest_bytes.size());
+ parameter_section_bytes += pcr_digest_bytes;
+ command_size += pcr_digest_bytes.size();
+ hash->Update(pcrs_bytes.data(),
+ pcrs_bytes.size());
+ parameter_section_bytes += pcrs_bytes;
+ command_size += pcrs_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyPCR(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyPCR;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyPCRErrorCallback(
+ const Tpm::PolicyPCRResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyPCRResponseParser(
+ const Tpm::PolicyPCRResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyPCRErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyPCR(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyPCR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPCRResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyPCRErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyPCRResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyPCR(
+ policy_session,
+ policy_session_name,
+ pcr_digest,
+ pcrs,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyPCRSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyPCR(
+ policy_session,
+ policy_session_name,
+ pcr_digest,
+ pcrs,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyPCR(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyLocality(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyLocality;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string locality_bytes;
+ rc = Serialize_TPMA_LOCALITY(
+ locality,
+ &locality_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(locality_bytes.data(),
+ locality_bytes.size());
+ parameter_section_bytes += locality_bytes;
+ command_size += locality_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyLocality(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyLocality;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyLocalityErrorCallback(
+ const Tpm::PolicyLocalityResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyLocalityResponseParser(
+ const Tpm::PolicyLocalityResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyLocalityErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyLocality(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyLocality(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyLocalityResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyLocalityErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyLocalityResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyLocality(
+ policy_session,
+ policy_session_name,
+ locality,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyLocalitySync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyLocality(
+ policy_session,
+ policy_session_name,
+ locality,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyLocality(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyNV(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyNV;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string operand_b_bytes;
+ rc = Serialize_TPM2B_OPERAND(
+ operand_b,
+ &operand_b_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string offset_bytes;
+ rc = Serialize_UINT16(
+ offset,
+ &offset_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string operation_bytes;
+ rc = Serialize_TPM_EO(
+ operation,
+ &operation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = operand_b_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ operand_b_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(operand_b_bytes.data(),
+ operand_b_bytes.size());
+ parameter_section_bytes += operand_b_bytes;
+ command_size += operand_b_bytes.size();
+ hash->Update(offset_bytes.data(),
+ offset_bytes.size());
+ parameter_section_bytes += offset_bytes;
+ command_size += offset_bytes.size();
+ hash->Update(operation_bytes.data(),
+ operation_bytes.size());
+ parameter_section_bytes += operation_bytes;
+ command_size += operation_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyNV(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyNV;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyNVErrorCallback(
+ const Tpm::PolicyNVResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyNVResponseParser(
+ const Tpm::PolicyNVResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyNVErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyNV(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyNV(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNVResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyNVErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyNVResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyNV(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ policy_session,
+ policy_session_name,
+ operand_b,
+ offset,
+ operation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyNVSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyNV(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ policy_session,
+ policy_session_name,
+ operand_b,
+ offset,
+ operation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyNV(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyCounterTimer(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyCounterTimer;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string operand_b_bytes;
+ rc = Serialize_TPM2B_OPERAND(
+ operand_b,
+ &operand_b_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string offset_bytes;
+ rc = Serialize_UINT16(
+ offset,
+ &offset_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string operation_bytes;
+ rc = Serialize_TPM_EO(
+ operation,
+ &operation_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = operand_b_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ operand_b_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(operand_b_bytes.data(),
+ operand_b_bytes.size());
+ parameter_section_bytes += operand_b_bytes;
+ command_size += operand_b_bytes.size();
+ hash->Update(offset_bytes.data(),
+ offset_bytes.size());
+ parameter_section_bytes += offset_bytes;
+ command_size += offset_bytes.size();
+ hash->Update(operation_bytes.data(),
+ operation_bytes.size());
+ parameter_section_bytes += operation_bytes;
+ command_size += operation_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyCounterTimer(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyCounterTimer;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyCounterTimerErrorCallback(
+ const Tpm::PolicyCounterTimerResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyCounterTimerResponseParser(
+ const Tpm::PolicyCounterTimerResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyCounterTimerErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyCounterTimer(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyCounterTimer(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCounterTimerResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyCounterTimerErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyCounterTimerResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyCounterTimer(
+ policy_session,
+ policy_session_name,
+ operand_b,
+ offset,
+ operation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyCounterTimerSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyCounterTimer(
+ policy_session,
+ policy_session_name,
+ operand_b,
+ offset,
+ operation,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyCounterTimer(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyCommandCode(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyCommandCode;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string code_bytes;
+ rc = Serialize_TPM_CC(
+ code,
+ &code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(code_bytes.data(),
+ code_bytes.size());
+ parameter_section_bytes += code_bytes;
+ command_size += code_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyCommandCode(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyCommandCode;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyCommandCodeErrorCallback(
+ const Tpm::PolicyCommandCodeResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyCommandCodeResponseParser(
+ const Tpm::PolicyCommandCodeResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyCommandCodeErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyCommandCode(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyCommandCode(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCommandCodeResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyCommandCodeErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyCommandCodeResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyCommandCode(
+ policy_session,
+ policy_session_name,
+ code,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyCommandCodeSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyCommandCode(
+ policy_session,
+ policy_session_name,
+ code,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyCommandCode(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyPhysicalPresence(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyPhysicalPresence;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyPhysicalPresence(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyPhysicalPresence;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyPhysicalPresenceErrorCallback(
+ const Tpm::PolicyPhysicalPresenceResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyPhysicalPresenceResponseParser(
+ const Tpm::PolicyPhysicalPresenceResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyPhysicalPresenceErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyPhysicalPresence(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyPhysicalPresence(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPhysicalPresenceResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyPhysicalPresenceErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyPhysicalPresenceResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyPhysicalPresence(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyPhysicalPresenceSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyPhysicalPresence(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyPhysicalPresence(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyCpHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyCpHash;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string cp_hash_a_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ cp_hash_a,
+ &cp_hash_a_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = cp_hash_a_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ cp_hash_a_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(cp_hash_a_bytes.data(),
+ cp_hash_a_bytes.size());
+ parameter_section_bytes += cp_hash_a_bytes;
+ command_size += cp_hash_a_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyCpHash(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyCpHash;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyCpHashErrorCallback(
+ const Tpm::PolicyCpHashResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyCpHashResponseParser(
+ const Tpm::PolicyCpHashResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyCpHashErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyCpHash(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyCpHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCpHashResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyCpHashErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyCpHashResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyCpHash(
+ policy_session,
+ policy_session_name,
+ cp_hash_a,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyCpHashSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyCpHash(
+ policy_session,
+ policy_session_name,
+ cp_hash_a,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyCpHash(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyNameHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyNameHash;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string name_hash_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ name_hash,
+ &name_hash_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = name_hash_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ name_hash_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(name_hash_bytes.data(),
+ name_hash_bytes.size());
+ parameter_section_bytes += name_hash_bytes;
+ command_size += name_hash_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyNameHash(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyNameHash;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyNameHashErrorCallback(
+ const Tpm::PolicyNameHashResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyNameHashResponseParser(
+ const Tpm::PolicyNameHashResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyNameHashErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyNameHash(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyNameHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNameHashResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyNameHashErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyNameHashResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyNameHash(
+ policy_session,
+ policy_session_name,
+ name_hash,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyNameHashSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyNameHash(
+ policy_session,
+ policy_session_name,
+ name_hash,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyNameHash(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyDuplicationSelect(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyDuplicationSelect;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_name_bytes;
+ rc = Serialize_TPM2B_NAME(
+ object_name,
+ &object_name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_parent_name_bytes;
+ rc = Serialize_TPM2B_NAME(
+ new_parent_name,
+ &new_parent_name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string include_object_bytes;
+ rc = Serialize_TPMI_YES_NO(
+ include_object,
+ &include_object_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = object_name_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ object_name_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(object_name_bytes.data(),
+ object_name_bytes.size());
+ parameter_section_bytes += object_name_bytes;
+ command_size += object_name_bytes.size();
+ hash->Update(new_parent_name_bytes.data(),
+ new_parent_name_bytes.size());
+ parameter_section_bytes += new_parent_name_bytes;
+ command_size += new_parent_name_bytes.size();
+ hash->Update(include_object_bytes.data(),
+ include_object_bytes.size());
+ parameter_section_bytes += include_object_bytes;
+ command_size += include_object_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyDuplicationSelect(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyDuplicationSelect;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyDuplicationSelectErrorCallback(
+ const Tpm::PolicyDuplicationSelectResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyDuplicationSelectResponseParser(
+ const Tpm::PolicyDuplicationSelectResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyDuplicationSelectErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyDuplicationSelect(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyDuplicationSelect(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyDuplicationSelectResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyDuplicationSelectErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyDuplicationSelectResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyDuplicationSelect(
+ policy_session,
+ policy_session_name,
+ object_name,
+ new_parent_name,
+ include_object,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyDuplicationSelectSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyDuplicationSelect(
+ policy_session,
+ policy_session_name,
+ object_name,
+ new_parent_name,
+ include_object,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyDuplicationSelect(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyAuthorize(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyAuthorize;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string approved_policy_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ approved_policy,
+ &approved_policy_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_ref_bytes;
+ rc = Serialize_TPM2B_NONCE(
+ policy_ref,
+ &policy_ref_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_sign_bytes;
+ rc = Serialize_TPM2B_NAME(
+ key_sign,
+ &key_sign_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string check_ticket_bytes;
+ rc = Serialize_TPMT_TK_VERIFIED(
+ check_ticket,
+ &check_ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = approved_policy_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ approved_policy_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(approved_policy_bytes.data(),
+ approved_policy_bytes.size());
+ parameter_section_bytes += approved_policy_bytes;
+ command_size += approved_policy_bytes.size();
+ hash->Update(policy_ref_bytes.data(),
+ policy_ref_bytes.size());
+ parameter_section_bytes += policy_ref_bytes;
+ command_size += policy_ref_bytes.size();
+ hash->Update(key_sign_bytes.data(),
+ key_sign_bytes.size());
+ parameter_section_bytes += key_sign_bytes;
+ command_size += key_sign_bytes.size();
+ hash->Update(check_ticket_bytes.data(),
+ check_ticket_bytes.size());
+ parameter_section_bytes += check_ticket_bytes;
+ command_size += check_ticket_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyAuthorize(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyAuthorize;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyAuthorizeErrorCallback(
+ const Tpm::PolicyAuthorizeResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyAuthorizeResponseParser(
+ const Tpm::PolicyAuthorizeResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyAuthorizeErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyAuthorize(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyAuthorize(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyAuthorizeResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyAuthorizeErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyAuthorizeResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyAuthorize(
+ policy_session,
+ policy_session_name,
+ approved_policy,
+ policy_ref,
+ key_sign,
+ check_ticket,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyAuthorizeSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyAuthorize(
+ policy_session,
+ policy_session_name,
+ approved_policy,
+ policy_ref,
+ key_sign,
+ check_ticket,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyAuthorize(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyAuthValue(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyAuthValue;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyAuthValue(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyAuthValue;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyAuthValueErrorCallback(
+ const Tpm::PolicyAuthValueResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyAuthValueResponseParser(
+ const Tpm::PolicyAuthValueResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyAuthValueErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyAuthValue(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyAuthValue(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyAuthValueResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyAuthValueErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyAuthValueResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyAuthValue(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyAuthValueSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyAuthValue(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyAuthValue(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyPassword(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyPassword;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyPassword(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyPassword;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyPasswordErrorCallback(
+ const Tpm::PolicyPasswordResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyPasswordResponseParser(
+ const Tpm::PolicyPasswordResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyPasswordErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyPassword(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyPassword(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPasswordResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyPasswordErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyPasswordResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyPassword(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyPasswordSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyPassword(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyPassword(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyGetDigest(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyGetDigest;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyGetDigest(
+ const std::string& response,
+ TPM2B_DIGEST* policy_digest,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyGetDigest;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string policy_digest_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ policy_digest,
+ &policy_digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = policy_digest_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ policy_digest_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_DIGEST(
+ &policy_digest_bytes,
+ policy_digest,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyGetDigestErrorCallback(
+ const Tpm::PolicyGetDigestResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_DIGEST());
+}
+
+void PolicyGetDigestResponseParser(
+ const Tpm::PolicyGetDigestResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyGetDigestErrorCallback, callback);
+ TPM2B_DIGEST policy_digest;
+ TPM_RC rc = Tpm::ParseResponse_PolicyGetDigest(
+ response,
+ &policy_digest,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ policy_digest);
+}
+
+void Tpm::PolicyGetDigest(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyGetDigestResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyGetDigestErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyGetDigestResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyGetDigest(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyGetDigestSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ TPM2B_DIGEST* policy_digest,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyGetDigest(
+ policy_session,
+ policy_session_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyGetDigest(
+ response,
+ policy_digest,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PolicyNvWritten(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PolicyNvWritten;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string policy_session_bytes;
+ rc = Serialize_TPMI_SH_POLICY(
+ policy_session,
+ &policy_session_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string written_set_bytes;
+ rc = Serialize_TPMI_YES_NO(
+ written_set,
+ &written_set_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(policy_session_name.data(),
+ policy_session_name.size());
+ handle_section_bytes += policy_session_bytes;
+ command_size += policy_session_bytes.size();
+ hash->Update(written_set_bytes.data(),
+ written_set_bytes.size());
+ parameter_section_bytes += written_set_bytes;
+ command_size += written_set_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PolicyNvWritten(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PolicyNvWritten;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PolicyNvWrittenErrorCallback(
+ const Tpm::PolicyNvWrittenResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PolicyNvWrittenResponseParser(
+ const Tpm::PolicyNvWrittenResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyNvWrittenErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PolicyNvWritten(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PolicyNvWritten(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNvWrittenResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PolicyNvWrittenErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PolicyNvWrittenResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyNvWritten(
+ policy_session,
+ policy_session_name,
+ written_set,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PolicyNvWrittenSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PolicyNvWritten(
+ policy_session,
+ policy_session_name,
+ written_set,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PolicyNvWritten(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_CreatePrimary(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_CreatePrimary;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string primary_handle_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY(
+ primary_handle,
+ &primary_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_sensitive_bytes;
+ rc = Serialize_TPM2B_SENSITIVE_CREATE(
+ in_sensitive,
+ &in_sensitive_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_public_bytes;
+ rc = Serialize_TPM2B_PUBLIC(
+ in_public,
+ &in_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string outside_info_bytes;
+ rc = Serialize_TPM2B_DATA(
+ outside_info,
+ &outside_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_pcr_bytes;
+ rc = Serialize_TPML_PCR_SELECTION(
+ creation_pcr,
+ &creation_pcr_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = in_sensitive_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ in_sensitive_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(primary_handle_name.data(),
+ primary_handle_name.size());
+ handle_section_bytes += primary_handle_bytes;
+ command_size += primary_handle_bytes.size();
+ hash->Update(in_sensitive_bytes.data(),
+ in_sensitive_bytes.size());
+ parameter_section_bytes += in_sensitive_bytes;
+ command_size += in_sensitive_bytes.size();
+ hash->Update(in_public_bytes.data(),
+ in_public_bytes.size());
+ parameter_section_bytes += in_public_bytes;
+ command_size += in_public_bytes.size();
+ hash->Update(outside_info_bytes.data(),
+ outside_info_bytes.size());
+ parameter_section_bytes += outside_info_bytes;
+ command_size += outside_info_bytes.size();
+ hash->Update(creation_pcr_bytes.data(),
+ creation_pcr_bytes.size());
+ parameter_section_bytes += creation_pcr_bytes;
+ command_size += creation_pcr_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_CreatePrimary(
+ const std::string& response,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string object_handle_bytes;
+ rc = Parse_TPM_HANDLE(
+ &buffer,
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_CreatePrimary;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string out_public_bytes;
+ rc = Parse_TPM2B_PUBLIC(
+ &buffer,
+ out_public,
+ &out_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_data_bytes;
+ rc = Parse_TPM2B_CREATION_DATA(
+ &buffer,
+ creation_data,
+ &creation_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_hash_bytes;
+ rc = Parse_TPM2B_DIGEST(
+ &buffer,
+ creation_hash,
+ &creation_hash_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string creation_ticket_bytes;
+ rc = Parse_TPMT_TK_CREATION(
+ &buffer,
+ creation_ticket,
+ &creation_ticket_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string name_bytes;
+ rc = Parse_TPM2B_NAME(
+ &buffer,
+ name,
+ &name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = out_public_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ out_public_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_PUBLIC(
+ &out_public_bytes,
+ out_public,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void CreatePrimaryErrorCallback(
+ const Tpm::CreatePrimaryResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM_HANDLE(),
+ TPM2B_PUBLIC(),
+ TPM2B_CREATION_DATA(),
+ TPM2B_DIGEST(),
+ TPMT_TK_CREATION(),
+ TPM2B_NAME());
+}
+
+void CreatePrimaryResponseParser(
+ const Tpm::CreatePrimaryResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CreatePrimaryErrorCallback, callback);
+ TPM_HANDLE object_handle;
+ TPM2B_PUBLIC out_public;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ TPM2B_NAME name;
+ TPM_RC rc = Tpm::ParseResponse_CreatePrimary(
+ response,
+ &object_handle,
+ &out_public,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket,
+ &name,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ object_handle,
+ out_public,
+ creation_data,
+ creation_hash,
+ creation_ticket,
+ name);
+}
+
+void Tpm::CreatePrimary(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ AuthorizationDelegate* authorization_delegate,
+ const CreatePrimaryResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(CreatePrimaryErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(CreatePrimaryResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_CreatePrimary(
+ primary_handle,
+ primary_handle_name,
+ in_sensitive,
+ in_public,
+ outside_info,
+ creation_pcr,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::CreatePrimarySync(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_CreatePrimary(
+ primary_handle,
+ primary_handle_name,
+ in_sensitive,
+ in_public,
+ outside_info,
+ creation_pcr,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_CreatePrimary(
+ response,
+ object_handle,
+ out_public,
+ creation_data,
+ creation_hash,
+ creation_ticket,
+ name,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_HierarchyControl(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_HierarchyControl;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string enable_bytes;
+ rc = Serialize_TPMI_RH_ENABLES(
+ enable,
+ &enable_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string state_bytes;
+ rc = Serialize_TPMI_YES_NO(
+ state,
+ &state_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(enable_bytes.data(),
+ enable_bytes.size());
+ parameter_section_bytes += enable_bytes;
+ command_size += enable_bytes.size();
+ hash->Update(state_bytes.data(),
+ state_bytes.size());
+ parameter_section_bytes += state_bytes;
+ command_size += state_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_HierarchyControl(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_HierarchyControl;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void HierarchyControlErrorCallback(
+ const Tpm::HierarchyControlResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void HierarchyControlResponseParser(
+ const Tpm::HierarchyControlResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HierarchyControlErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_HierarchyControl(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::HierarchyControl(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ AuthorizationDelegate* authorization_delegate,
+ const HierarchyControlResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HierarchyControlErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(HierarchyControlResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_HierarchyControl(
+ auth_handle,
+ auth_handle_name,
+ enable,
+ state,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::HierarchyControlSync(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_HierarchyControl(
+ auth_handle,
+ auth_handle_name,
+ enable,
+ state,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_HierarchyControl(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_SetPrimaryPolicy(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_SetPrimaryPolicy;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_policy_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ auth_policy,
+ &auth_policy_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string hash_alg_bytes;
+ rc = Serialize_TPMI_ALG_HASH(
+ hash_alg,
+ &hash_alg_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = auth_policy_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ auth_policy_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(auth_policy_bytes.data(),
+ auth_policy_bytes.size());
+ parameter_section_bytes += auth_policy_bytes;
+ command_size += auth_policy_bytes.size();
+ hash->Update(hash_alg_bytes.data(),
+ hash_alg_bytes.size());
+ parameter_section_bytes += hash_alg_bytes;
+ command_size += hash_alg_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_SetPrimaryPolicy(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_SetPrimaryPolicy;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SetPrimaryPolicyErrorCallback(
+ const Tpm::SetPrimaryPolicyResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void SetPrimaryPolicyResponseParser(
+ const Tpm::SetPrimaryPolicyResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SetPrimaryPolicyErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_SetPrimaryPolicy(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::SetPrimaryPolicy(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const SetPrimaryPolicyResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SetPrimaryPolicyErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SetPrimaryPolicyResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_SetPrimaryPolicy(
+ auth_handle,
+ auth_handle_name,
+ auth_policy,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SetPrimaryPolicySync(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_SetPrimaryPolicy(
+ auth_handle,
+ auth_handle_name,
+ auth_policy,
+ hash_alg,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_SetPrimaryPolicy(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ChangePPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ChangePPS;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ChangePPS(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ChangePPS;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ChangePPSErrorCallback(
+ const Tpm::ChangePPSResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ChangePPSResponseParser(
+ const Tpm::ChangePPSResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ChangePPSErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_ChangePPS(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::ChangePPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ChangePPSResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ChangePPSErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ChangePPSResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ChangePPS(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ChangePPSSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ChangePPS(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ChangePPS(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ChangeEPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ChangeEPS;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ChangeEPS(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ChangeEPS;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ChangeEPSErrorCallback(
+ const Tpm::ChangeEPSResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ChangeEPSResponseParser(
+ const Tpm::ChangeEPSResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ChangeEPSErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_ChangeEPS(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::ChangeEPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ChangeEPSResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ChangeEPSErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ChangeEPSResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ChangeEPS(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ChangeEPSSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ChangeEPS(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ChangeEPS(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_Clear(
+ const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_Clear;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_CLEAR(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_Clear(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_Clear;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ClearErrorCallback(
+ const Tpm::ClearResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ClearResponseParser(
+ const Tpm::ClearResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClearErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_Clear(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::Clear(
+ const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ClearResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClearErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ClearResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_Clear(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ClearSync(
+ const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_Clear(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_Clear(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ClearControl(
+ const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ClearControl;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMI_RH_CLEAR(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string disable_bytes;
+ rc = Serialize_TPMI_YES_NO(
+ disable,
+ &disable_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_name.data(),
+ auth_name.size());
+ handle_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(disable_bytes.data(),
+ disable_bytes.size());
+ parameter_section_bytes += disable_bytes;
+ command_size += disable_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ClearControl(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ClearControl;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ClearControlErrorCallback(
+ const Tpm::ClearControlResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ClearControlResponseParser(
+ const Tpm::ClearControlResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClearControlErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_ClearControl(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::ClearControl(
+ const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ AuthorizationDelegate* authorization_delegate,
+ const ClearControlResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClearControlErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ClearControlResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ClearControl(
+ auth,
+ auth_name,
+ disable,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ClearControlSync(
+ const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ClearControl(
+ auth,
+ auth_name,
+ disable,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ClearControl(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_HierarchyChangeAuth(
+ const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_HierarchyChangeAuth;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_HIERARCHY_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_auth_bytes;
+ rc = Serialize_TPM2B_AUTH(
+ new_auth,
+ &new_auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = new_auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ new_auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(new_auth_bytes.data(),
+ new_auth_bytes.size());
+ parameter_section_bytes += new_auth_bytes;
+ command_size += new_auth_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_HierarchyChangeAuth(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_HierarchyChangeAuth;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void HierarchyChangeAuthErrorCallback(
+ const Tpm::HierarchyChangeAuthResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void HierarchyChangeAuthResponseParser(
+ const Tpm::HierarchyChangeAuthResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HierarchyChangeAuthErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_HierarchyChangeAuth(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::HierarchyChangeAuth(
+ const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const HierarchyChangeAuthResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(HierarchyChangeAuthErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(HierarchyChangeAuthResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_HierarchyChangeAuth(
+ auth_handle,
+ auth_handle_name,
+ new_auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::HierarchyChangeAuthSync(
+ const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_HierarchyChangeAuth(
+ auth_handle,
+ auth_handle_name,
+ new_auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_HierarchyChangeAuth(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_DictionaryAttackLockReset(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_DictionaryAttackLockReset;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string lock_handle_bytes;
+ rc = Serialize_TPMI_RH_LOCKOUT(
+ lock_handle,
+ &lock_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(lock_handle_name.data(),
+ lock_handle_name.size());
+ handle_section_bytes += lock_handle_bytes;
+ command_size += lock_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_DictionaryAttackLockReset(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_DictionaryAttackLockReset;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void DictionaryAttackLockResetErrorCallback(
+ const Tpm::DictionaryAttackLockResetResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void DictionaryAttackLockResetResponseParser(
+ const Tpm::DictionaryAttackLockResetResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(DictionaryAttackLockResetErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_DictionaryAttackLockReset(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::DictionaryAttackLockReset(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const DictionaryAttackLockResetResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(DictionaryAttackLockResetErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(DictionaryAttackLockResetResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_DictionaryAttackLockReset(
+ lock_handle,
+ lock_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::DictionaryAttackLockResetSync(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_DictionaryAttackLockReset(
+ lock_handle,
+ lock_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_DictionaryAttackLockReset(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_DictionaryAttackParameters(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_DictionaryAttackParameters;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string lock_handle_bytes;
+ rc = Serialize_TPMI_RH_LOCKOUT(
+ lock_handle,
+ &lock_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_max_tries_bytes;
+ rc = Serialize_UINT32(
+ new_max_tries,
+ &new_max_tries_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_recovery_time_bytes;
+ rc = Serialize_UINT32(
+ new_recovery_time,
+ &new_recovery_time_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string lockout_recovery_bytes;
+ rc = Serialize_UINT32(
+ lockout_recovery,
+ &lockout_recovery_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(lock_handle_name.data(),
+ lock_handle_name.size());
+ handle_section_bytes += lock_handle_bytes;
+ command_size += lock_handle_bytes.size();
+ hash->Update(new_max_tries_bytes.data(),
+ new_max_tries_bytes.size());
+ parameter_section_bytes += new_max_tries_bytes;
+ command_size += new_max_tries_bytes.size();
+ hash->Update(new_recovery_time_bytes.data(),
+ new_recovery_time_bytes.size());
+ parameter_section_bytes += new_recovery_time_bytes;
+ command_size += new_recovery_time_bytes.size();
+ hash->Update(lockout_recovery_bytes.data(),
+ lockout_recovery_bytes.size());
+ parameter_section_bytes += lockout_recovery_bytes;
+ command_size += lockout_recovery_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_DictionaryAttackParameters(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_DictionaryAttackParameters;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void DictionaryAttackParametersErrorCallback(
+ const Tpm::DictionaryAttackParametersResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void DictionaryAttackParametersResponseParser(
+ const Tpm::DictionaryAttackParametersResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(DictionaryAttackParametersErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_DictionaryAttackParameters(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::DictionaryAttackParameters(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ AuthorizationDelegate* authorization_delegate,
+ const DictionaryAttackParametersResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(DictionaryAttackParametersErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(DictionaryAttackParametersResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_DictionaryAttackParameters(
+ lock_handle,
+ lock_handle_name,
+ new_max_tries,
+ new_recovery_time,
+ lockout_recovery,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::DictionaryAttackParametersSync(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_DictionaryAttackParameters(
+ lock_handle,
+ lock_handle_name,
+ new_max_tries,
+ new_recovery_time,
+ lockout_recovery,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_DictionaryAttackParameters(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_PP_Commands(
+ const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_PP_Commands;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string set_list_bytes;
+ rc = Serialize_TPML_CC(
+ set_list,
+ &set_list_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string clear_list_bytes;
+ rc = Serialize_TPML_CC(
+ clear_list,
+ &clear_list_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_name.data(),
+ auth_name.size());
+ handle_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(set_list_bytes.data(),
+ set_list_bytes.size());
+ parameter_section_bytes += set_list_bytes;
+ command_size += set_list_bytes.size();
+ hash->Update(clear_list_bytes.data(),
+ clear_list_bytes.size());
+ parameter_section_bytes += clear_list_bytes;
+ command_size += clear_list_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_PP_Commands(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_PP_Commands;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void PP_CommandsErrorCallback(
+ const Tpm::PP_CommandsResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void PP_CommandsResponseParser(
+ const Tpm::PP_CommandsResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PP_CommandsErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_PP_Commands(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::PP_Commands(
+ const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate,
+ const PP_CommandsResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(PP_CommandsErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(PP_CommandsResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_PP_Commands(
+ auth,
+ auth_name,
+ set_list,
+ clear_list,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::PP_CommandsSync(
+ const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_PP_Commands(
+ auth,
+ auth_name,
+ set_list,
+ clear_list,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_PP_Commands(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_SetAlgorithmSet(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_SetAlgorithmSet;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string algorithm_set_bytes;
+ rc = Serialize_UINT32(
+ algorithm_set,
+ &algorithm_set_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(algorithm_set_bytes.data(),
+ algorithm_set_bytes.size());
+ parameter_section_bytes += algorithm_set_bytes;
+ command_size += algorithm_set_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_SetAlgorithmSet(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_SetAlgorithmSet;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void SetAlgorithmSetErrorCallback(
+ const Tpm::SetAlgorithmSetResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void SetAlgorithmSetResponseParser(
+ const Tpm::SetAlgorithmSetResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SetAlgorithmSetErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_SetAlgorithmSet(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::SetAlgorithmSet(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ AuthorizationDelegate* authorization_delegate,
+ const SetAlgorithmSetResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(SetAlgorithmSetErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(SetAlgorithmSetResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_SetAlgorithmSet(
+ auth_handle,
+ auth_handle_name,
+ algorithm_set,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::SetAlgorithmSetSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_SetAlgorithmSet(
+ auth_handle,
+ auth_handle_name,
+ algorithm_set,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_SetAlgorithmSet(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_FieldUpgradeStart(
+ const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_FieldUpgradeStart;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ authorization,
+ &authorization_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string key_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ key_handle,
+ &key_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string fu_digest_bytes;
+ rc = Serialize_TPM2B_DIGEST(
+ fu_digest,
+ &fu_digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string manifest_signature_bytes;
+ rc = Serialize_TPMT_SIGNATURE(
+ manifest_signature,
+ &manifest_signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = fu_digest_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ fu_digest_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(authorization_name.data(),
+ authorization_name.size());
+ handle_section_bytes += authorization_bytes;
+ command_size += authorization_bytes.size();
+ hash->Update(key_handle_name.data(),
+ key_handle_name.size());
+ handle_section_bytes += key_handle_bytes;
+ command_size += key_handle_bytes.size();
+ hash->Update(fu_digest_bytes.data(),
+ fu_digest_bytes.size());
+ parameter_section_bytes += fu_digest_bytes;
+ command_size += fu_digest_bytes.size();
+ hash->Update(manifest_signature_bytes.data(),
+ manifest_signature_bytes.size());
+ parameter_section_bytes += manifest_signature_bytes;
+ command_size += manifest_signature_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_FieldUpgradeStart(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_FieldUpgradeStart;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void FieldUpgradeStartErrorCallback(
+ const Tpm::FieldUpgradeStartResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void FieldUpgradeStartResponseParser(
+ const Tpm::FieldUpgradeStartResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FieldUpgradeStartErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_FieldUpgradeStart(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::FieldUpgradeStart(
+ const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ AuthorizationDelegate* authorization_delegate,
+ const FieldUpgradeStartResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FieldUpgradeStartErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(FieldUpgradeStartResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_FieldUpgradeStart(
+ authorization,
+ authorization_name,
+ key_handle,
+ key_handle_name,
+ fu_digest,
+ manifest_signature,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::FieldUpgradeStartSync(
+ const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_FieldUpgradeStart(
+ authorization,
+ authorization_name,
+ key_handle,
+ key_handle_name,
+ fu_digest,
+ manifest_signature,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_FieldUpgradeStart(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_FieldUpgradeData(
+ const TPM2B_MAX_BUFFER& fu_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_FieldUpgradeData;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string fu_data_bytes;
+ rc = Serialize_TPM2B_MAX_BUFFER(
+ fu_data,
+ &fu_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = fu_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ fu_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(fu_data_bytes.data(),
+ fu_data_bytes.size());
+ parameter_section_bytes += fu_data_bytes;
+ command_size += fu_data_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_FieldUpgradeData(
+ const std::string& response,
+ TPMT_HA* next_digest,
+ TPMT_HA* first_digest,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_FieldUpgradeData;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string next_digest_bytes;
+ rc = Parse_TPMT_HA(
+ &buffer,
+ next_digest,
+ &next_digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string first_digest_bytes;
+ rc = Parse_TPMT_HA(
+ &buffer,
+ first_digest,
+ &first_digest_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void FieldUpgradeDataErrorCallback(
+ const Tpm::FieldUpgradeDataResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMT_HA(),
+ TPMT_HA());
+}
+
+void FieldUpgradeDataResponseParser(
+ const Tpm::FieldUpgradeDataResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FieldUpgradeDataErrorCallback, callback);
+ TPMT_HA next_digest;
+ TPMT_HA first_digest;
+ TPM_RC rc = Tpm::ParseResponse_FieldUpgradeData(
+ response,
+ &next_digest,
+ &first_digest,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ next_digest,
+ first_digest);
+}
+
+void Tpm::FieldUpgradeData(
+ const TPM2B_MAX_BUFFER& fu_data,
+ AuthorizationDelegate* authorization_delegate,
+ const FieldUpgradeDataResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FieldUpgradeDataErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(FieldUpgradeDataResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_FieldUpgradeData(
+ fu_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::FieldUpgradeDataSync(
+ const TPM2B_MAX_BUFFER& fu_data,
+ TPMT_HA* next_digest,
+ TPMT_HA* first_digest,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_FieldUpgradeData(
+ fu_data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_FieldUpgradeData(
+ response,
+ next_digest,
+ first_digest,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_FirmwareRead(
+ const UINT32& sequence_number,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_FirmwareRead;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sequence_number_bytes;
+ rc = Serialize_UINT32(
+ sequence_number,
+ &sequence_number_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sequence_number_bytes.data(),
+ sequence_number_bytes.size());
+ parameter_section_bytes += sequence_number_bytes;
+ command_size += sequence_number_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_FirmwareRead(
+ const std::string& response,
+ TPM2B_MAX_BUFFER* fu_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_FirmwareRead;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string fu_data_bytes;
+ rc = Parse_TPM2B_MAX_BUFFER(
+ &buffer,
+ fu_data,
+ &fu_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = fu_data_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ fu_data_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_MAX_BUFFER(
+ &fu_data_bytes,
+ fu_data,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void FirmwareReadErrorCallback(
+ const Tpm::FirmwareReadResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_MAX_BUFFER());
+}
+
+void FirmwareReadResponseParser(
+ const Tpm::FirmwareReadResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FirmwareReadErrorCallback, callback);
+ TPM2B_MAX_BUFFER fu_data;
+ TPM_RC rc = Tpm::ParseResponse_FirmwareRead(
+ response,
+ &fu_data,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ fu_data);
+}
+
+void Tpm::FirmwareRead(
+ const UINT32& sequence_number,
+ AuthorizationDelegate* authorization_delegate,
+ const FirmwareReadResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FirmwareReadErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(FirmwareReadResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_FirmwareRead(
+ sequence_number,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::FirmwareReadSync(
+ const UINT32& sequence_number,
+ TPM2B_MAX_BUFFER* fu_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_FirmwareRead(
+ sequence_number,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_FirmwareRead(
+ response,
+ fu_data,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ContextSave(
+ const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ContextSave;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string save_handle_bytes;
+ rc = Serialize_TPMI_DH_CONTEXT(
+ save_handle,
+ &save_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(save_handle_name.data(),
+ save_handle_name.size());
+ handle_section_bytes += save_handle_bytes;
+ command_size += save_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ContextSave(
+ const std::string& response,
+ TPMS_CONTEXT* context,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ContextSave;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string context_bytes;
+ rc = Parse_TPMS_CONTEXT(
+ &buffer,
+ context,
+ &context_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ContextSaveErrorCallback(
+ const Tpm::ContextSaveResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMS_CONTEXT());
+}
+
+void ContextSaveResponseParser(
+ const Tpm::ContextSaveResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ContextSaveErrorCallback, callback);
+ TPMS_CONTEXT context;
+ TPM_RC rc = Tpm::ParseResponse_ContextSave(
+ response,
+ &context,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ context);
+}
+
+void Tpm::ContextSave(
+ const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ContextSaveResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ContextSaveErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ContextSaveResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ContextSave(
+ save_handle,
+ save_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ContextSaveSync(
+ const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ TPMS_CONTEXT* context,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ContextSave(
+ save_handle,
+ save_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ContextSave(
+ response,
+ context,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ContextLoad(
+ const TPMS_CONTEXT& context,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ContextLoad;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string context_bytes;
+ rc = Serialize_TPMS_CONTEXT(
+ context,
+ &context_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(context_bytes.data(),
+ context_bytes.size());
+ parameter_section_bytes += context_bytes;
+ command_size += context_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ContextLoad(
+ const std::string& response,
+ TPMI_DH_CONTEXT* loaded_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ std::string loaded_handle_bytes;
+ rc = Parse_TPMI_DH_CONTEXT(
+ &buffer,
+ loaded_handle,
+ &loaded_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_CC command_code = TPM_CC_ContextLoad;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ContextLoadErrorCallback(
+ const Tpm::ContextLoadResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMI_DH_CONTEXT());
+}
+
+void ContextLoadResponseParser(
+ const Tpm::ContextLoadResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ContextLoadErrorCallback, callback);
+ TPMI_DH_CONTEXT loaded_handle;
+ TPM_RC rc = Tpm::ParseResponse_ContextLoad(
+ response,
+ &loaded_handle,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ loaded_handle);
+}
+
+void Tpm::ContextLoad(
+ const TPMS_CONTEXT& context,
+ AuthorizationDelegate* authorization_delegate,
+ const ContextLoadResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ContextLoadErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ContextLoadResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ContextLoad(
+ context,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ContextLoadSync(
+ const TPMS_CONTEXT& context,
+ TPMI_DH_CONTEXT* loaded_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ContextLoad(
+ context,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ContextLoad(
+ response,
+ loaded_handle,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_FlushContext(
+ const TPMI_DH_CONTEXT& flush_handle,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_FlushContext;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string flush_handle_bytes;
+ rc = Serialize_TPMI_DH_CONTEXT(
+ flush_handle,
+ &flush_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(flush_handle_bytes.data(),
+ flush_handle_bytes.size());
+ parameter_section_bytes += flush_handle_bytes;
+ command_size += flush_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_FlushContext(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_FlushContext;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void FlushContextErrorCallback(
+ const Tpm::FlushContextResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void FlushContextResponseParser(
+ const Tpm::FlushContextResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FlushContextErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_FlushContext(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::FlushContext(
+ const TPMI_DH_CONTEXT& flush_handle,
+ AuthorizationDelegate* authorization_delegate,
+ const FlushContextResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(FlushContextErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(FlushContextResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_FlushContext(
+ flush_handle,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::FlushContextSync(
+ const TPMI_DH_CONTEXT& flush_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_FlushContext(
+ flush_handle,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_FlushContext(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_EvictControl(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_EvictControl;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string object_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ object_handle,
+ &object_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string persistent_handle_bytes;
+ rc = Serialize_TPMI_DH_PERSISTENT(
+ persistent_handle,
+ &persistent_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_name.data(),
+ auth_name.size());
+ handle_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(object_handle_name.data(),
+ object_handle_name.size());
+ handle_section_bytes += object_handle_bytes;
+ command_size += object_handle_bytes.size();
+ hash->Update(persistent_handle_bytes.data(),
+ persistent_handle_bytes.size());
+ parameter_section_bytes += persistent_handle_bytes;
+ command_size += persistent_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_EvictControl(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_EvictControl;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void EvictControlErrorCallback(
+ const Tpm::EvictControlResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void EvictControlResponseParser(
+ const Tpm::EvictControlResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EvictControlErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_EvictControl(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::EvictControl(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ AuthorizationDelegate* authorization_delegate,
+ const EvictControlResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(EvictControlErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(EvictControlResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_EvictControl(
+ auth,
+ auth_name,
+ object_handle,
+ object_handle_name,
+ persistent_handle,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::EvictControlSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_EvictControl(
+ auth,
+ auth_name,
+ object_handle,
+ object_handle_name,
+ persistent_handle,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_EvictControl(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ReadClock(
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ReadClock;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ReadClock(
+ const std::string& response,
+ TPMS_TIME_INFO* current_time,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ReadClock;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string current_time_bytes;
+ rc = Parse_TPMS_TIME_INFO(
+ &buffer,
+ current_time,
+ &current_time_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ReadClockErrorCallback(
+ const Tpm::ReadClockResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMS_TIME_INFO());
+}
+
+void ReadClockResponseParser(
+ const Tpm::ReadClockResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ReadClockErrorCallback, callback);
+ TPMS_TIME_INFO current_time;
+ TPM_RC rc = Tpm::ParseResponse_ReadClock(
+ response,
+ &current_time,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ current_time);
+}
+
+void Tpm::ReadClock(
+ AuthorizationDelegate* authorization_delegate,
+ const ReadClockResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ReadClockErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ReadClockResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ReadClock(
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ReadClockSync(
+ TPMS_TIME_INFO* current_time,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ReadClock(
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ReadClock(
+ response,
+ current_time,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ClockSet(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ClockSet;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_time_bytes;
+ rc = Serialize_UINT64(
+ new_time,
+ &new_time_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_name.data(),
+ auth_name.size());
+ handle_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(new_time_bytes.data(),
+ new_time_bytes.size());
+ parameter_section_bytes += new_time_bytes;
+ command_size += new_time_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ClockSet(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ClockSet;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ClockSetErrorCallback(
+ const Tpm::ClockSetResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ClockSetResponseParser(
+ const Tpm::ClockSetResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClockSetErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_ClockSet(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::ClockSet(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ AuthorizationDelegate* authorization_delegate,
+ const ClockSetResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClockSetErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ClockSetResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ClockSet(
+ auth,
+ auth_name,
+ new_time,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ClockSetSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ClockSet(
+ auth,
+ auth_name,
+ new_time,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ClockSet(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_ClockRateAdjust(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_ClockRateAdjust;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string rate_adjust_bytes;
+ rc = Serialize_TPM_CLOCK_ADJUST(
+ rate_adjust,
+ &rate_adjust_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_name.data(),
+ auth_name.size());
+ handle_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(rate_adjust_bytes.data(),
+ rate_adjust_bytes.size());
+ parameter_section_bytes += rate_adjust_bytes;
+ command_size += rate_adjust_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_ClockRateAdjust(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_ClockRateAdjust;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void ClockRateAdjustErrorCallback(
+ const Tpm::ClockRateAdjustResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void ClockRateAdjustResponseParser(
+ const Tpm::ClockRateAdjustResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClockRateAdjustErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_ClockRateAdjust(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::ClockRateAdjust(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ AuthorizationDelegate* authorization_delegate,
+ const ClockRateAdjustResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(ClockRateAdjustErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(ClockRateAdjustResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_ClockRateAdjust(
+ auth,
+ auth_name,
+ rate_adjust,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::ClockRateAdjustSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_ClockRateAdjust(
+ auth,
+ auth_name,
+ rate_adjust,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_ClockRateAdjust(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_GetCapability(
+ const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_GetCapability;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string capability_bytes;
+ rc = Serialize_TPM_CAP(
+ capability,
+ &capability_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string property_bytes;
+ rc = Serialize_UINT32(
+ property,
+ &property_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string property_count_bytes;
+ rc = Serialize_UINT32(
+ property_count,
+ &property_count_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(capability_bytes.data(),
+ capability_bytes.size());
+ parameter_section_bytes += capability_bytes;
+ command_size += capability_bytes.size();
+ hash->Update(property_bytes.data(),
+ property_bytes.size());
+ parameter_section_bytes += property_bytes;
+ command_size += property_bytes.size();
+ hash->Update(property_count_bytes.data(),
+ property_count_bytes.size());
+ parameter_section_bytes += property_count_bytes;
+ command_size += property_count_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_GetCapability(
+ const std::string& response,
+ TPMI_YES_NO* more_data,
+ TPMS_CAPABILITY_DATA* capability_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_GetCapability;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string more_data_bytes;
+ rc = Parse_TPMI_YES_NO(
+ &buffer,
+ more_data,
+ &more_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string capability_data_bytes;
+ rc = Parse_TPMS_CAPABILITY_DATA(
+ &buffer,
+ capability_data,
+ &capability_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void GetCapabilityErrorCallback(
+ const Tpm::GetCapabilityResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPMI_YES_NO(),
+ TPMS_CAPABILITY_DATA());
+}
+
+void GetCapabilityResponseParser(
+ const Tpm::GetCapabilityResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetCapabilityErrorCallback, callback);
+ TPMI_YES_NO more_data;
+ TPMS_CAPABILITY_DATA capability_data;
+ TPM_RC rc = Tpm::ParseResponse_GetCapability(
+ response,
+ &more_data,
+ &capability_data,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ more_data,
+ capability_data);
+}
+
+void Tpm::GetCapability(
+ const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ AuthorizationDelegate* authorization_delegate,
+ const GetCapabilityResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(GetCapabilityErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(GetCapabilityResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetCapability(
+ capability,
+ property,
+ property_count,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::GetCapabilitySync(
+ const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ TPMI_YES_NO* more_data,
+ TPMS_CAPABILITY_DATA* capability_data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_GetCapability(
+ capability,
+ property,
+ property_count,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_GetCapability(
+ response,
+ more_data,
+ capability_data,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_TestParms(
+ const TPMT_PUBLIC_PARMS& parameters,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_TestParms;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string parameters_bytes;
+ rc = Serialize_TPMT_PUBLIC_PARMS(
+ parameters,
+ &parameters_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(parameters_bytes.data(),
+ parameters_bytes.size());
+ parameter_section_bytes += parameters_bytes;
+ command_size += parameters_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_TestParms(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_TestParms;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void TestParmsErrorCallback(
+ const Tpm::TestParmsResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void TestParmsResponseParser(
+ const Tpm::TestParmsResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(TestParmsErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_TestParms(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::TestParms(
+ const TPMT_PUBLIC_PARMS& parameters,
+ AuthorizationDelegate* authorization_delegate,
+ const TestParmsResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(TestParmsErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(TestParmsResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_TestParms(
+ parameters,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::TestParmsSync(
+ const TPMT_PUBLIC_PARMS& parameters,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_TestParms(
+ parameters,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_TestParms(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_DefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_DefineSpace;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_bytes;
+ rc = Serialize_TPM2B_AUTH(
+ auth,
+ &auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string public_info_bytes;
+ rc = Serialize_TPM2B_NV_PUBLIC(
+ public_info,
+ &public_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(auth_bytes.data(),
+ auth_bytes.size());
+ parameter_section_bytes += auth_bytes;
+ command_size += auth_bytes.size();
+ hash->Update(public_info_bytes.data(),
+ public_info_bytes.size());
+ parameter_section_bytes += public_info_bytes;
+ command_size += public_info_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_DefineSpace(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_DefineSpace;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_DefineSpaceErrorCallback(
+ const Tpm::NV_DefineSpaceResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_DefineSpaceResponseParser(
+ const Tpm::NV_DefineSpaceResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_DefineSpaceErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_DefineSpace(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_DefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_DefineSpaceResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_DefineSpaceErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_DefineSpaceResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_DefineSpace(
+ auth_handle,
+ auth_handle_name,
+ auth,
+ public_info,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_DefineSpaceSync(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_DefineSpace(
+ auth_handle,
+ auth_handle_name,
+ auth,
+ public_info,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_DefineSpace(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_UndefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_UndefineSpace;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_UndefineSpace(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_UndefineSpace;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_UndefineSpaceErrorCallback(
+ const Tpm::NV_UndefineSpaceResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_UndefineSpaceResponseParser(
+ const Tpm::NV_UndefineSpaceResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_UndefineSpaceErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_UndefineSpace(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_UndefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_UndefineSpaceResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_UndefineSpaceErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_UndefineSpaceResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_UndefineSpace(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_UndefineSpaceSync(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_UndefineSpace(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_UndefineSpace(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_UndefineSpaceSpecial(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_UndefineSpaceSpecial;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string platform_bytes;
+ rc = Serialize_TPMI_RH_PLATFORM(
+ platform,
+ &platform_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(platform_name.data(),
+ platform_name.size());
+ handle_section_bytes += platform_bytes;
+ command_size += platform_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_UndefineSpaceSpecial(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_UndefineSpaceSpecial;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_UndefineSpaceSpecialErrorCallback(
+ const Tpm::NV_UndefineSpaceSpecialResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_UndefineSpaceSpecialResponseParser(
+ const Tpm::NV_UndefineSpaceSpecialResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_UndefineSpaceSpecialErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_UndefineSpaceSpecial(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_UndefineSpaceSpecial(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_UndefineSpaceSpecialResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_UndefineSpaceSpecialErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_UndefineSpaceSpecialResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_UndefineSpaceSpecial(
+ nv_index,
+ nv_index_name,
+ platform,
+ platform_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_UndefineSpaceSpecialSync(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_UndefineSpaceSpecial(
+ nv_index,
+ nv_index_name,
+ platform,
+ platform_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_UndefineSpaceSpecial(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_ReadPublic(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_ReadPublic;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_ReadPublic(
+ const std::string& response,
+ TPM2B_NV_PUBLIC* nv_public,
+ TPM2B_NAME* nv_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_ReadPublic;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string nv_public_bytes;
+ rc = Parse_TPM2B_NV_PUBLIC(
+ &buffer,
+ nv_public,
+ &nv_public_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_name_bytes;
+ rc = Parse_TPM2B_NAME(
+ &buffer,
+ nv_name,
+ &nv_name_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = nv_public_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ nv_public_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_NV_PUBLIC(
+ &nv_public_bytes,
+ nv_public,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_ReadPublicErrorCallback(
+ const Tpm::NV_ReadPublicResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_NV_PUBLIC(),
+ TPM2B_NAME());
+}
+
+void NV_ReadPublicResponseParser(
+ const Tpm::NV_ReadPublicResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ReadPublicErrorCallback, callback);
+ TPM2B_NV_PUBLIC nv_public;
+ TPM2B_NAME nv_name;
+ TPM_RC rc = Tpm::ParseResponse_NV_ReadPublic(
+ response,
+ &nv_public,
+ &nv_name,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ nv_public,
+ nv_name);
+}
+
+void Tpm::NV_ReadPublic(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadPublicResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ReadPublicErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_ReadPublicResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_ReadPublic(
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_ReadPublicSync(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ TPM2B_NV_PUBLIC* nv_public,
+ TPM2B_NAME* nv_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_ReadPublic(
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_ReadPublic(
+ response,
+ nv_public,
+ nv_name,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_Write(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_Write;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string data_bytes;
+ rc = Serialize_TPM2B_MAX_NV_BUFFER(
+ data,
+ &data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string offset_bytes;
+ rc = Serialize_UINT16(
+ offset,
+ &offset_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(data_bytes.data(),
+ data_bytes.size());
+ parameter_section_bytes += data_bytes;
+ command_size += data_bytes.size();
+ hash->Update(offset_bytes.data(),
+ offset_bytes.size());
+ parameter_section_bytes += offset_bytes;
+ command_size += offset_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_Write(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_Write;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_WriteErrorCallback(
+ const Tpm::NV_WriteResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_WriteResponseParser(
+ const Tpm::NV_WriteResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_WriteErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_Write(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_Write(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_WriteResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_WriteErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_WriteResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Write(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ data,
+ offset,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_WriteSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Write(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ data,
+ offset,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_Write(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_Increment(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_Increment;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_Increment(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_Increment;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_IncrementErrorCallback(
+ const Tpm::NV_IncrementResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_IncrementResponseParser(
+ const Tpm::NV_IncrementResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_IncrementErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_Increment(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_Increment(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_IncrementResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_IncrementErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_IncrementResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Increment(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_IncrementSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Increment(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_Increment(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_Extend(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_Extend;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string data_bytes;
+ rc = Serialize_TPM2B_MAX_NV_BUFFER(
+ data,
+ &data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(data_bytes.data(),
+ data_bytes.size());
+ parameter_section_bytes += data_bytes;
+ command_size += data_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_Extend(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_Extend;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_ExtendErrorCallback(
+ const Tpm::NV_ExtendResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_ExtendResponseParser(
+ const Tpm::NV_ExtendResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ExtendErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_Extend(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_Extend(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ExtendResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ExtendErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_ExtendResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Extend(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_ExtendSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Extend(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ data,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_Extend(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_SetBits(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_SetBits;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string bits_bytes;
+ rc = Serialize_UINT64(
+ bits,
+ &bits_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(bits_bytes.data(),
+ bits_bytes.size());
+ parameter_section_bytes += bits_bytes;
+ command_size += bits_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_SetBits(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_SetBits;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_SetBitsErrorCallback(
+ const Tpm::NV_SetBitsResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_SetBitsResponseParser(
+ const Tpm::NV_SetBitsResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_SetBitsErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_SetBits(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_SetBits(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_SetBitsResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_SetBitsErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_SetBitsResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_SetBits(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ bits,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_SetBitsSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_SetBits(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ bits,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_SetBits(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_WriteLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_WriteLock;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_WriteLock(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_WriteLock;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_WriteLockErrorCallback(
+ const Tpm::NV_WriteLockResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_WriteLockResponseParser(
+ const Tpm::NV_WriteLockResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_WriteLockErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_WriteLock(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_WriteLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_WriteLockResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_WriteLockErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_WriteLockResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_WriteLock(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_WriteLockSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_WriteLock(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_WriteLock(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_GlobalWriteLock(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_GlobalWriteLock;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_PROVISION(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_GlobalWriteLock(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_GlobalWriteLock;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_GlobalWriteLockErrorCallback(
+ const Tpm::NV_GlobalWriteLockResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_GlobalWriteLockResponseParser(
+ const Tpm::NV_GlobalWriteLockResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_GlobalWriteLockErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_GlobalWriteLock(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_GlobalWriteLock(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_GlobalWriteLockResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_GlobalWriteLockErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_GlobalWriteLockResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_GlobalWriteLock(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_GlobalWriteLockSync(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_GlobalWriteLock(
+ auth_handle,
+ auth_handle_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_GlobalWriteLock(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_Read(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_Read;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string size_bytes;
+ rc = Serialize_UINT16(
+ size,
+ &size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string offset_bytes;
+ rc = Serialize_UINT16(
+ offset,
+ &offset_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(size_bytes.data(),
+ size_bytes.size());
+ parameter_section_bytes += size_bytes;
+ command_size += size_bytes.size();
+ hash->Update(offset_bytes.data(),
+ offset_bytes.size());
+ parameter_section_bytes += offset_bytes;
+ command_size += offset_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_Read(
+ const std::string& response,
+ TPM2B_MAX_NV_BUFFER* data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_Read;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string data_bytes;
+ rc = Parse_TPM2B_MAX_NV_BUFFER(
+ &buffer,
+ data,
+ &data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = data_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ data_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_MAX_NV_BUFFER(
+ &data_bytes,
+ data,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_ReadErrorCallback(
+ const Tpm::NV_ReadResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_MAX_NV_BUFFER());
+}
+
+void NV_ReadResponseParser(
+ const Tpm::NV_ReadResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ReadErrorCallback, callback);
+ TPM2B_MAX_NV_BUFFER data;
+ TPM_RC rc = Tpm::ParseResponse_NV_Read(
+ response,
+ &data,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ data);
+}
+
+void Tpm::NV_Read(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ReadErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_ReadResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Read(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ size,
+ offset,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_ReadSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_MAX_NV_BUFFER* data,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Read(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ size,
+ offset,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_Read(
+ response,
+ data,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_ReadLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_ReadLock;
+ bool is_command_parameter_encryption_possible = false;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_ReadLock(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_ReadLock;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_ReadLockErrorCallback(
+ const Tpm::NV_ReadLockResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_ReadLockResponseParser(
+ const Tpm::NV_ReadLockResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ReadLockErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_ReadLock(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_ReadLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadLockResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ReadLockErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_ReadLockResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_ReadLock(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_ReadLockSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_ReadLock(
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_ReadLock(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_ChangeAuth(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_ChangeAuth;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = false;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string new_auth_bytes;
+ rc = Serialize_TPM2B_AUTH(
+ new_auth,
+ &new_auth_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = new_auth_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ new_auth_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(new_auth_bytes.data(),
+ new_auth_bytes.size());
+ parameter_section_bytes += new_auth_bytes;
+ command_size += new_auth_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_ChangeAuth(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_ChangeAuth;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_ChangeAuthErrorCallback(
+ const Tpm::NV_ChangeAuthResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code);
+}
+
+void NV_ChangeAuthResponseParser(
+ const Tpm::NV_ChangeAuthResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ChangeAuthErrorCallback, callback);
+ TPM_RC rc = Tpm::ParseResponse_NV_ChangeAuth(
+ response,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc);
+}
+
+void Tpm::NV_ChangeAuth(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ChangeAuthResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_ChangeAuthErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_ChangeAuthResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_ChangeAuth(
+ nv_index,
+ nv_index_name,
+ new_auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_ChangeAuthSync(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_ChangeAuth(
+ nv_index,
+ nv_index_name,
+ new_auth,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_ChangeAuth(
+ response,
+ authorization_delegate);
+ return rc;
+}
+
+TPM_RC Tpm::SerializeCommand_NV_Certify(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ TPM_RC rc = TPM_RC_SUCCESS;
+ TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
+ UINT32 command_size = 10; // Header size.
+ std::string handle_section_bytes;
+ std::string parameter_section_bytes;
+ TPM_CC command_code = TPM_CC_NV_Certify;
+ bool is_command_parameter_encryption_possible = true;
+ bool is_response_parameter_encryption_possible = true;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string sign_handle_bytes;
+ rc = Serialize_TPMI_DH_OBJECT(
+ sign_handle,
+ &sign_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string auth_handle_bytes;
+ rc = Serialize_TPMI_RH_NV_AUTH(
+ auth_handle,
+ &auth_handle_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string nv_index_bytes;
+ rc = Serialize_TPMI_RH_NV_INDEX(
+ nv_index,
+ &nv_index_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string qualifying_data_bytes;
+ rc = Serialize_TPM2B_DATA(
+ qualifying_data,
+ &qualifying_data_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string in_scheme_bytes;
+ rc = Serialize_TPMT_SIG_SCHEME(
+ in_scheme,
+ &in_scheme_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string size_bytes;
+ rc = Serialize_UINT16(
+ size,
+ &size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string offset_bytes;
+ rc = Serialize_UINT16(
+ offset,
+ &offset_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (authorization_delegate) {
+ // Encrypt just the parameter data, not the size.
+ std::string tmp = qualifying_data_bytes.substr(2);
+ if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ qualifying_data_bytes.replace(2, std::string::npos, tmp);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(sign_handle_name.data(),
+ sign_handle_name.size());
+ handle_section_bytes += sign_handle_bytes;
+ command_size += sign_handle_bytes.size();
+ hash->Update(auth_handle_name.data(),
+ auth_handle_name.size());
+ handle_section_bytes += auth_handle_bytes;
+ command_size += auth_handle_bytes.size();
+ hash->Update(nv_index_name.data(),
+ nv_index_name.size());
+ handle_section_bytes += nv_index_bytes;
+ command_size += nv_index_bytes.size();
+ hash->Update(qualifying_data_bytes.data(),
+ qualifying_data_bytes.size());
+ parameter_section_bytes += qualifying_data_bytes;
+ command_size += qualifying_data_bytes.size();
+ hash->Update(in_scheme_bytes.data(),
+ in_scheme_bytes.size());
+ parameter_section_bytes += in_scheme_bytes;
+ command_size += in_scheme_bytes.size();
+ hash->Update(size_bytes.data(),
+ size_bytes.size());
+ parameter_section_bytes += size_bytes;
+ command_size += size_bytes.size();
+ hash->Update(offset_bytes.data(),
+ offset_bytes.size());
+ parameter_section_bytes += offset_bytes;
+ command_size += offset_bytes.size();
+ std::string command_hash(32, 0);
+ hash->Finish(string_as_array(&command_hash), command_hash.size());
+ std::string authorization_section_bytes;
+ std::string authorization_size_bytes;
+ if (authorization_delegate) {
+ if (!authorization_delegate->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ &authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ if (!authorization_section_bytes.empty()) {
+ tag = TPM_ST_SESSIONS;
+ std::string tmp;
+ rc = Serialize_UINT32(authorization_section_bytes.size(),
+ &authorization_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ command_size += authorization_size_bytes.size() +
+ authorization_section_bytes.size();
+ }
+ }
+ std::string tag_bytes;
+ rc = Serialize_TPMI_ST_COMMAND_TAG(
+ tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string command_size_bytes;
+ rc = Serialize_UINT32(
+ command_size,
+ &command_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ *serialized_command = tag_bytes +
+ command_size_bytes +
+ command_code_bytes +
+ handle_section_bytes +
+ authorization_size_bytes +
+ authorization_section_bytes +
+ parameter_section_bytes;
+ CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
+ VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
+ serialized_command->size());
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC Tpm::ParseResponse_NV_Certify(
+ const std::string& response,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(3) << __func__;
+ VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
+ TPM_RC rc = TPM_RC_SUCCESS;
+ std::string buffer(response);
+ TPM_ST tag;
+ std::string tag_bytes;
+ rc = Parse_TPM_ST(
+ &buffer,
+ &tag,
+ &tag_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ UINT32 response_size;
+ std::string response_size_bytes;
+ rc = Parse_UINT32(
+ &buffer,
+ &response_size,
+ &response_size_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ TPM_RC response_code;
+ std::string response_code_bytes;
+ rc = Parse_TPM_RC(
+ &buffer,
+ &response_code,
+ &response_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (response_size != response.size()) {
+ return TPM_RC_SIZE;
+ }
+ if (response_code != TPM_RC_SUCCESS) {
+ return response_code;
+ }
+ TPM_CC command_code = TPM_CC_NV_Certify;
+ std::string command_code_bytes;
+ rc = Serialize_TPM_CC(
+ command_code,
+ &command_code_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string authorization_section_bytes;
+ if (tag == TPM_ST_SESSIONS) {
+ UINT32 parameter_section_size = buffer.size();
+ rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (parameter_section_size > buffer.size()) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ authorization_section_bytes = buffer.substr(parameter_section_size);
+ // Keep the parameter section in |buffer|.
+ buffer.erase(parameter_section_size);
+ }
+ scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
+ crypto::SecureHash::SHA256));
+ hash->Update(response_code_bytes.data(),
+ response_code_bytes.size());
+ hash->Update(command_code_bytes.data(),
+ command_code_bytes.size());
+ hash->Update(buffer.data(),
+ buffer.size());
+ std::string response_hash(32, 0);
+ hash->Finish(string_as_array(&response_hash), response_hash.size());
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ if (!authorization_delegate->CheckResponseAuthorization(
+ response_hash,
+ authorization_section_bytes)) {
+ return TRUNKS_RC_AUTHORIZATION_FAILED;
+ }
+ }
+ std::string certify_info_bytes;
+ rc = Parse_TPM2B_ATTEST(
+ &buffer,
+ certify_info,
+ &certify_info_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string signature_bytes;
+ rc = Parse_TPMT_SIGNATURE(
+ &buffer,
+ signature,
+ &signature_bytes);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ if (tag == TPM_ST_SESSIONS) {
+ CHECK(authorization_delegate) << "Authorization delegate missing!";
+ // Decrypt just the parameter data, not the size.
+ std::string tmp = certify_info_bytes.substr(2);
+ if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
+ return TRUNKS_RC_ENCRYPTION_FAILED;
+ }
+ certify_info_bytes.replace(2, std::string::npos, tmp);
+ rc = Parse_TPM2B_ATTEST(
+ &certify_info_bytes,
+ certify_info,
+ nullptr);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+void NV_CertifyErrorCallback(
+ const Tpm::NV_CertifyResponse& callback,
+ TPM_RC response_code) {
+ VLOG(1) << __func__;
+ callback.Run(response_code,
+ TPM2B_ATTEST(),
+ TPMT_SIGNATURE());
+}
+
+void NV_CertifyResponseParser(
+ const Tpm::NV_CertifyResponse& callback,
+ AuthorizationDelegate* authorization_delegate,
+ const std::string& response) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_CertifyErrorCallback, callback);
+ TPM2B_ATTEST certify_info;
+ TPMT_SIGNATURE signature;
+ TPM_RC rc = Tpm::ParseResponse_NV_Certify(
+ response,
+ &certify_info,
+ &signature,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ callback.Run(
+ rc,
+ certify_info,
+ signature);
+}
+
+void Tpm::NV_Certify(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_CertifyResponse& callback) {
+ VLOG(1) << __func__;
+ base::Callback<void(TPM_RC)> error_reporter =
+ base::Bind(NV_CertifyErrorCallback, callback);
+ base::Callback<void(const std::string&)> parser =
+ base::Bind(NV_CertifyResponseParser,
+ callback,
+ authorization_delegate);
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Certify(
+ sign_handle,
+ sign_handle_name,
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ qualifying_data,
+ in_scheme,
+ size,
+ offset,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ error_reporter.Run(rc);
+ return;
+ }
+ transceiver_->SendCommand(command, parser);
+}
+
+TPM_RC Tpm::NV_CertifySync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate) {
+ VLOG(1) << __func__;
+ std::string command;
+ TPM_RC rc = SerializeCommand_NV_Certify(
+ sign_handle,
+ sign_handle_name,
+ auth_handle,
+ auth_handle_name,
+ nv_index,
+ nv_index_name,
+ qualifying_data,
+ in_scheme,
+ size,
+ offset,
+ &command,
+ authorization_delegate);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+ std::string response = transceiver_->SendCommandAndWait(command);
+ rc = ParseResponse_NV_Certify(
+ response,
+ certify_info,
+ signature,
+ authorization_delegate);
+ return rc;
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_generated.h b/trunks/tpm_generated.h
new file mode 100644
index 0000000..5a7c7e0
--- /dev/null
+++ b/trunks/tpm_generated.h
@@ -0,0 +1,6691 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+// THIS CODE IS GENERATED - DO NOT MODIFY!
+
+#ifndef TRUNKS_TPM_GENERATED_H_
+#define TRUNKS_TPM_GENERATED_H_
+
+#include <string>
+
+#include <base/basictypes.h>
+#include <base/callback_forward.h>
+
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class AuthorizationDelegate;
+class CommandTransceiver;
+
+#if !defined(SHA1_DIGEST_SIZE)
+#define SHA1_DIGEST_SIZE 20
+#endif
+#if !defined(SHA1_BLOCK_SIZE)
+#define SHA1_BLOCK_SIZE 64
+#endif
+#if !defined(SHA1_DER_SIZE)
+#define SHA1_DER_SIZE 15
+#endif
+#if !defined(SHA1_DER)
+#define SHA1_DER {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}
+#endif
+#if !defined(SHA256_DIGEST_SIZE)
+#define SHA256_DIGEST_SIZE 32
+#endif
+#if !defined(SHA256_BLOCK_SIZE)
+#define SHA256_BLOCK_SIZE 64
+#endif
+#if !defined(SHA256_DER_SIZE)
+#define SHA256_DER_SIZE 19
+#endif
+#if !defined(SHA256_DER)
+#define SHA256_DER {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}
+#endif
+#if !defined(SHA384_DIGEST_SIZE)
+#define SHA384_DIGEST_SIZE 48
+#endif
+#if !defined(SHA384_BLOCK_SIZE)
+#define SHA384_BLOCK_SIZE 128
+#endif
+#if !defined(SHA384_DER_SIZE)
+#define SHA384_DER_SIZE 19
+#endif
+#if !defined(SHA384_DER)
+#define SHA384_DER {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30}
+#endif
+#if !defined(SHA512_DIGEST_SIZE)
+#define SHA512_DIGEST_SIZE 64
+#endif
+#if !defined(SHA512_BLOCK_SIZE)
+#define SHA512_BLOCK_SIZE 128
+#endif
+#if !defined(SHA512_DER_SIZE)
+#define SHA512_DER_SIZE 19
+#endif
+#if !defined(SHA512_DER)
+#define SHA512_DER {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40}
+#endif
+#if !defined(SM3_256_DIGEST_SIZE)
+#define SM3_256_DIGEST_SIZE 32
+#endif
+#if !defined(SM3_256_BLOCK_SIZE)
+#define SM3_256_BLOCK_SIZE 64
+#endif
+#if !defined(SM3_256_DER_SIZE)
+#define SM3_256_DER_SIZE 18
+#endif
+#if !defined(SM3_256_DER)
+#define SM3_256_DER {0x30,0x30,0x30,0x0c,0x06,0x08,0x2a,0x81,0x1c,0x81,0x45,0x01,0x83,0x11,0x05,0x00,0x04,0x20}
+#endif
+#if !defined(MAX_SESSION_NUMBER)
+#define MAX_SESSION_NUMBER 3
+#endif
+#if !defined(YES)
+#define YES 1
+#endif
+#if !defined(NO)
+#define NO 0
+#endif
+#if !defined(TRUE)
+#define TRUE 1
+#endif
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(SET)
+#define SET 1
+#endif
+#if !defined(CLEAR)
+#define CLEAR 0
+#endif
+#if !defined(BIG_ENDIAN_TPM)
+#define BIG_ENDIAN_TPM NO
+#endif
+#if !defined(LITTLE_ENDIAN_TPM)
+#define LITTLE_ENDIAN_TPM YES
+#endif
+#if !defined(NO_AUTO_ALIGN)
+#define NO_AUTO_ALIGN NO
+#endif
+#if !defined(RSA_KEY_SIZES_BITS)
+#define RSA_KEY_SIZES_BITS {1024, 2048}
+#endif
+#if !defined(MAX_RSA_KEY_BITS)
+#define MAX_RSA_KEY_BITS 2048
+#endif
+#if !defined(MAX_RSA_KEY_BYTES)
+#define MAX_RSA_KEY_BYTES ((MAX_RSA_KEY_BITS + 7) / 8)
+#endif
+#if !defined(ECC_CURVES)
+#define ECC_CURVES {TPM_ECC_NIST_P256, TPM_ECC_BN_P256, TPM_ECC_SM2_P256}
+#endif
+#if !defined(ECC_KEY_SIZES_BITS)
+#define ECC_KEY_SIZES_BITS {256}
+#endif
+#if !defined(MAX_ECC_KEY_BITS)
+#define MAX_ECC_KEY_BITS 256
+#endif
+#if !defined(MAX_ECC_KEY_BYTES)
+#define MAX_ECC_KEY_BYTES ((MAX_ECC_KEY_BITS + 7) / 8)
+#endif
+#if !defined(AES_KEY_SIZES_BITS)
+#define AES_KEY_SIZES_BITS {128}
+#endif
+#if !defined(MAX_AES_KEY_BITS)
+#define MAX_AES_KEY_BITS 128
+#endif
+#if !defined(MAX_AES_BLOCK_SIZE_BYTES)
+#define MAX_AES_BLOCK_SIZE_BYTES 16
+#endif
+#if !defined(MAX_AES_KEY_BYTES)
+#define MAX_AES_KEY_BYTES ((MAX_AES_KEY_BITS + 7) / 8)
+#endif
+#if !defined(SM4_KEY_SIZES_BITS)
+#define SM4_KEY_SIZES_BITS {128}
+#endif
+#if !defined(MAX_SM4_KEY_BITS)
+#define MAX_SM4_KEY_BITS 128
+#endif
+#if !defined(MAX_SM4_BLOCK_SIZE_BYTES)
+#define MAX_SM4_BLOCK_SIZE_BYTES 16
+#endif
+#if !defined(MAX_SM4_KEY_BYTES)
+#define MAX_SM4_KEY_BYTES ((MAX_SM4_KEY_BITS + 7) / 8)
+#endif
+#if !defined(MAX_SYM_KEY_BITS)
+#define MAX_SYM_KEY_BITS MAX_AES_KEY_BITS
+#endif
+#if !defined(MAX_SYM_KEY_BYTES)
+#define MAX_SYM_KEY_BYTES MAX_AES_KEY_BYTES
+#endif
+#if !defined(MAX_SYM_BLOCK_SIZE)
+#define MAX_SYM_BLOCK_SIZE MAX_AES_BLOCK_SIZE_BYTES
+#endif
+#if !defined(FIELD_UPGRADE_IMPLEMENTED)
+#define FIELD_UPGRADE_IMPLEMENTED NO
+#endif
+#if !defined(BSIZE)
+#define BSIZE UINT16
+#endif
+#if !defined(BUFFER_ALIGNMENT)
+#define BUFFER_ALIGNMENT 4
+#endif
+#if !defined(IMPLEMENTATION_PCR)
+#define IMPLEMENTATION_PCR 24
+#endif
+#if !defined(PLATFORM_PCR)
+#define PLATFORM_PCR 24
+#endif
+#if !defined(DRTM_PCR)
+#define DRTM_PCR 17
+#endif
+#if !defined(HCRTM_PCR)
+#define HCRTM_PCR 0
+#endif
+#if !defined(NUM_LOCALITIES)
+#define NUM_LOCALITIES 5
+#endif
+#if !defined(MAX_HANDLE_NUM)
+#define MAX_HANDLE_NUM 3
+#endif
+#if !defined(MAX_ACTIVE_SESSIONS)
+#define MAX_ACTIVE_SESSIONS 64
+#endif
+#if !defined(CONTEXT_SLOT)
+#define CONTEXT_SLOT UINT16
+#endif
+#if !defined(CONTEXT_COUNTER)
+#define CONTEXT_COUNTER UINT64
+#endif
+#if !defined(MAX_LOADED_SESSIONS)
+#define MAX_LOADED_SESSIONS 3
+#endif
+#if !defined(MAX_SESSION_NUM)
+#define MAX_SESSION_NUM 3
+#endif
+#if !defined(MAX_LOADED_OBJECTS)
+#define MAX_LOADED_OBJECTS 3
+#endif
+#if !defined(MIN_EVICT_OBJECTS)
+#define MIN_EVICT_OBJECTS 2
+#endif
+#if !defined(PCR_SELECT_MIN)
+#define PCR_SELECT_MIN ((PLATFORM_PCR+7)/8)
+#endif
+#if !defined(PCR_SELECT_MAX)
+#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR+7)/8)
+#endif
+#if !defined(NUM_POLICY_PCR_GROUP)
+#define NUM_POLICY_PCR_GROUP 1
+#endif
+#if !defined(NUM_AUTHVALUE_PCR_GROUP)
+#define NUM_AUTHVALUE_PCR_GROUP 1
+#endif
+#if !defined(MAX_CONTEXT_SIZE)
+#define MAX_CONTEXT_SIZE 4000
+#endif
+#if !defined(MAX_DIGEST_BUFFER)
+#define MAX_DIGEST_BUFFER 1024
+#endif
+#if !defined(MAX_NV_INDEX_SIZE)
+#define MAX_NV_INDEX_SIZE 2048
+#endif
+#if !defined(MAX_NV_BUFFER_SIZE)
+#define MAX_NV_BUFFER_SIZE 1024
+#endif
+#if !defined(MAX_CAP_BUFFER)
+#define MAX_CAP_BUFFER 1024
+#endif
+#if !defined(NV_MEMORY_SIZE)
+#define NV_MEMORY_SIZE 16384
+#endif
+#if !defined(NUM_STATIC_PCR)
+#define NUM_STATIC_PCR 16
+#endif
+#if !defined(MAX_ALG_LIST_SIZE)
+#define MAX_ALG_LIST_SIZE 64
+#endif
+#if !defined(TIMER_PRESCALE)
+#define TIMER_PRESCALE 100000
+#endif
+#if !defined(PRIMARY_SEED_SIZE)
+#define PRIMARY_SEED_SIZE 32
+#endif
+#if !defined(CONTEXT_ENCRYPT_ALG)
+#define CONTEXT_ENCRYPT_ALG TPM_ALG_AES
+#endif
+#if !defined(CONTEXT_ENCRYPT_KEY_BITS)
+#define CONTEXT_ENCRYPT_KEY_BITS MAX_SYM_KEY_BITS
+#endif
+#if !defined(CONTEXT_ENCRYPT_KEY_BYTES)
+#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8)
+#endif
+#if !defined(CONTEXT_INTEGRITY_HASH_ALG)
+#define CONTEXT_INTEGRITY_HASH_ALG TPM_ALG_SHA256
+#endif
+#if !defined(CONTEXT_INTEGRITY_HASH_SIZE)
+#define CONTEXT_INTEGRITY_HASH_SIZE SHA256_DIGEST_SIZE
+#endif
+#if !defined(PROOF_SIZE)
+#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE
+#endif
+#if !defined(NV_CLOCK_UPDATE_INTERVAL)
+#define NV_CLOCK_UPDATE_INTERVAL 12
+#endif
+#if !defined(NUM_POLICY_PCR)
+#define NUM_POLICY_PCR 1
+#endif
+#if !defined(MAX_COMMAND_SIZE)
+#define MAX_COMMAND_SIZE 4096
+#endif
+#if !defined(MAX_RESPONSE_SIZE)
+#define MAX_RESPONSE_SIZE 4096
+#endif
+#if !defined(ORDERLY_BITS)
+#define ORDERLY_BITS 8
+#endif
+#if !defined(MAX_ORDERLY_COUNT)
+#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1)
+#endif
+#if !defined(ALG_ID_FIRST)
+#define ALG_ID_FIRST TPM_ALG_FIRST
+#endif
+#if !defined(ALG_ID_LAST)
+#define ALG_ID_LAST TPM_ALG_LAST
+#endif
+#if !defined(MAX_SYM_DATA)
+#define MAX_SYM_DATA 128
+#endif
+#if !defined(MAX_RNG_ENTROPY_SIZE)
+#define MAX_RNG_ENTROPY_SIZE 64
+#endif
+#if !defined(RAM_INDEX_SPACE)
+#define RAM_INDEX_SPACE 512
+#endif
+#if !defined(RSA_DEFAULT_PUBLIC_EXPONENT)
+#define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001
+#endif
+#if !defined(ENABLE_PCR_NO_INCREMENT)
+#define ENABLE_PCR_NO_INCREMENT YES
+#endif
+#if !defined(CRT_FORMAT_RSA)
+#define CRT_FORMAT_RSA YES
+#endif
+#if !defined(PRIVATE_VENDOR_SPECIFIC_BYTES)
+#define PRIVATE_VENDOR_SPECIFIC_BYTES ((MAX_RSA_KEY_BYTES/2) * (3 + CRT_FORMAT_RSA * 2))
+#endif
+#if !defined(MAX_CAP_DATA)
+#define MAX_CAP_DATA (MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32))
+#endif
+#if !defined(MAX_CAP_ALGS)
+#define MAX_CAP_ALGS (TPM_ALG_LAST - TPM_ALG_FIRST + 1)
+#endif
+#if !defined(MAX_CAP_HANDLES)
+#define MAX_CAP_HANDLES (MAX_CAP_DATA/sizeof(TPM_HANDLE))
+#endif
+#if !defined(MAX_CAP_CC)
+#define MAX_CAP_CC ((TPM_CC_LAST - TPM_CC_FIRST) + 1)
+#endif
+#if !defined(MAX_TPM_PROPERTIES)
+#define MAX_TPM_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))
+#endif
+#if !defined(MAX_PCR_PROPERTIES)
+#define MAX_PCR_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT))
+#endif
+#if !defined(MAX_ECC_CURVES)
+#define MAX_ECC_CURVES (MAX_CAP_DATA/sizeof(TPM_ECC_CURVE))
+#endif
+#if !defined(HASH_COUNT)
+#define HASH_COUNT 3
+#endif
+
+typedef uint8_t UINT8;
+typedef uint8_t BYTE;
+typedef int8_t INT8;
+typedef int BOOL;
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef uint32_t UINT32;
+typedef int32_t INT32;
+typedef uint64_t UINT64;
+typedef int64_t INT64;
+typedef UINT32 TPM_ALGORITHM_ID;
+typedef UINT32 TPM_MODIFIER_INDICATOR;
+typedef UINT32 TPM_AUTHORIZATION_SIZE;
+typedef UINT32 TPM_PARAMETER_SIZE;
+typedef UINT16 TPM_KEY_SIZE;
+typedef UINT16 TPM_KEY_BITS;
+typedef UINT32 TPM_HANDLE;
+struct TPM2B_DIGEST;
+typedef TPM2B_DIGEST TPM2B_NONCE;
+typedef TPM2B_DIGEST TPM2B_AUTH;
+typedef TPM2B_DIGEST TPM2B_OPERAND;
+struct TPMS_SCHEME_SIGHASH;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_HMAC;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSASSA;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSAPSS;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECDSA;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_SM2;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECSCHNORR;
+typedef BYTE TPMI_YES_NO;
+typedef TPM_HANDLE TPMI_DH_OBJECT;
+typedef TPM_HANDLE TPMI_DH_PERSISTENT;
+typedef TPM_HANDLE TPMI_DH_ENTITY;
+typedef TPM_HANDLE TPMI_DH_PCR;
+typedef TPM_HANDLE TPMI_SH_AUTH_SESSION;
+typedef TPM_HANDLE TPMI_SH_HMAC;
+typedef TPM_HANDLE TPMI_SH_POLICY;
+typedef TPM_HANDLE TPMI_DH_CONTEXT;
+typedef TPM_HANDLE TPMI_RH_HIERARCHY;
+typedef TPM_HANDLE TPMI_RH_ENABLES;
+typedef TPM_HANDLE TPMI_RH_HIERARCHY_AUTH;
+typedef TPM_HANDLE TPMI_RH_PLATFORM;
+typedef TPM_HANDLE TPMI_RH_OWNER;
+typedef TPM_HANDLE TPMI_RH_ENDORSEMENT;
+typedef TPM_HANDLE TPMI_RH_PROVISION;
+typedef TPM_HANDLE TPMI_RH_CLEAR;
+typedef TPM_HANDLE TPMI_RH_NV_AUTH;
+typedef TPM_HANDLE TPMI_RH_LOCKOUT;
+typedef TPM_HANDLE TPMI_RH_NV_INDEX;
+typedef UINT16 TPM_ALG_ID;
+typedef TPM_ALG_ID TPMI_ALG_HASH;
+typedef TPM_ALG_ID TPMI_ALG_ASYM;
+typedef TPM_ALG_ID TPMI_ALG_SYM;
+typedef TPM_ALG_ID TPMI_ALG_SYM_OBJECT;
+typedef TPM_ALG_ID TPMI_ALG_SYM_MODE;
+typedef TPM_ALG_ID TPMI_ALG_KDF;
+typedef TPM_ALG_ID TPMI_ALG_SIG_SCHEME;
+typedef TPM_ALG_ID TPMI_ECC_KEY_EXCHANGE;
+typedef UINT16 TPM_ST;
+typedef TPM_ST TPMI_ST_COMMAND_TAG;
+typedef TPM_ST TPMI_ST_ATTEST;
+typedef TPM_KEY_BITS TPMI_AES_KEY_BITS;
+typedef TPM_KEY_BITS TPMI_SM4_KEY_BITS;
+typedef TPM_ALG_ID TPMI_ALG_KEYEDHASH_SCHEME;
+typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME;
+typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME;
+typedef TPM_ALG_ID TPMI_ALG_RSA_DECRYPT;
+typedef TPM_KEY_BITS TPMI_RSA_KEY_BITS;
+typedef TPM_ALG_ID TPMI_ALG_ECC_SCHEME;
+typedef UINT16 TPM_ECC_CURVE;
+typedef TPM_ECC_CURVE TPMI_ECC_CURVE;
+typedef TPM_ALG_ID TPMI_ALG_PUBLIC;
+typedef UINT32 TPMA_ALGORITHM;
+typedef UINT32 TPMA_OBJECT;
+typedef UINT8 TPMA_SESSION;
+typedef UINT8 TPMA_LOCALITY;
+typedef UINT32 TPMA_PERMANENT;
+typedef UINT32 TPMA_STARTUP_CLEAR;
+typedef UINT32 TPMA_MEMORY;
+typedef UINT32 TPM_CC;
+typedef TPM_CC TPMA_CC;
+typedef UINT32 TPM_NV_INDEX;
+typedef UINT32 TPMA_NV;
+typedef UINT32 TPM_SPEC;
+typedef UINT32 TPM_GENERATED;
+typedef UINT32 TPM_RC;
+typedef INT8 TPM_CLOCK_ADJUST;
+typedef UINT16 TPM_EO;
+typedef UINT16 TPM_SU;
+typedef UINT8 TPM_SE;
+typedef UINT32 TPM_CAP;
+typedef UINT32 TPM_PT;
+typedef UINT32 TPM_PT_PCR;
+typedef UINT32 TPM_PS;
+typedef UINT8 TPM_HT;
+typedef UINT32 TPM_RH;
+typedef TPM_HANDLE TPM_HC;
+
+const TPM_SPEC TPM_SPEC_FAMILY = 0x322E3000;
+const TPM_SPEC TPM_SPEC_LEVEL = 00;
+const TPM_SPEC TPM_SPEC_VERSION = 99;
+const TPM_SPEC TPM_SPEC_YEAR = 2013;
+const TPM_SPEC TPM_SPEC_DAY_OF_YEAR = 304;
+const TPM_GENERATED TPM_GENERATED_VALUE = 0xff544347;
+const TPM_ALG_ID TPM_ALG_ERROR = 0x0000;
+const TPM_ALG_ID TPM_ALG_FIRST = 0x0001;
+const TPM_ALG_ID TPM_ALG_RSA = 0x0001;
+const TPM_ALG_ID TPM_ALG_SHA = 0x0004;
+const TPM_ALG_ID TPM_ALG_SHA1 = 0x0004;
+const TPM_ALG_ID TPM_ALG_HMAC = 0x0005;
+const TPM_ALG_ID TPM_ALG_AES = 0x0006;
+const TPM_ALG_ID TPM_ALG_MGF1 = 0x0007;
+const TPM_ALG_ID TPM_ALG_KEYEDHASH = 0x0008;
+const TPM_ALG_ID TPM_ALG_XOR = 0x000A;
+const TPM_ALG_ID TPM_ALG_SHA256 = 0x000B;
+const TPM_ALG_ID TPM_ALG_SHA384 = 0x000C;
+const TPM_ALG_ID TPM_ALG_SHA512 = 0x000D;
+const TPM_ALG_ID TPM_ALG_NULL = 0x0010;
+const TPM_ALG_ID TPM_ALG_SM3_256 = 0x0012;
+const TPM_ALG_ID TPM_ALG_SM4 = 0x0013;
+const TPM_ALG_ID TPM_ALG_RSASSA = 0x0014;
+const TPM_ALG_ID TPM_ALG_RSAES = 0x0015;
+const TPM_ALG_ID TPM_ALG_RSAPSS = 0x0016;
+const TPM_ALG_ID TPM_ALG_OAEP = 0x0017;
+const TPM_ALG_ID TPM_ALG_ECDSA = 0x0018;
+const TPM_ALG_ID TPM_ALG_ECDH = 0x0019;
+const TPM_ALG_ID TPM_ALG_ECDAA = 0x001A;
+const TPM_ALG_ID TPM_ALG_SM2 = 0x001B;
+const TPM_ALG_ID TPM_ALG_ECSCHNORR = 0x001C;
+const TPM_ALG_ID TPM_ALG_ECMQV = 0x001D;
+const TPM_ALG_ID TPM_ALG_KDF1_SP800_56a = 0x0020;
+const TPM_ALG_ID TPM_ALG_KDF2 = 0x0021;
+const TPM_ALG_ID TPM_ALG_KDF1_SP800_108 = 0x0022;
+const TPM_ALG_ID TPM_ALG_ECC = 0x0023;
+const TPM_ALG_ID TPM_ALG_SYMCIPHER = 0x0025;
+const TPM_ALG_ID TPM_ALG_CTR = 0x0040;
+const TPM_ALG_ID TPM_ALG_OFB = 0x0041;
+const TPM_ALG_ID TPM_ALG_CBC = 0x0042;
+const TPM_ALG_ID TPM_ALG_CFB = 0x0043;
+const TPM_ALG_ID TPM_ALG_ECB = 0x0044;
+const TPM_ALG_ID TPM_ALG_LAST = 0x0044;
+const TPM_ECC_CURVE TPM_ECC_NONE = 0x0000;
+const TPM_ECC_CURVE TPM_ECC_NIST_P192 = 0x0001;
+const TPM_ECC_CURVE TPM_ECC_NIST_P224 = 0x0002;
+const TPM_ECC_CURVE TPM_ECC_NIST_P256 = 0x0003;
+const TPM_ECC_CURVE TPM_ECC_NIST_P384 = 0x0004;
+const TPM_ECC_CURVE TPM_ECC_NIST_P521 = 0x0005;
+const TPM_ECC_CURVE TPM_ECC_BN_P256 = 0x0010;
+const TPM_ECC_CURVE TPM_ECC_BN_P638 = 0x0011;
+const TPM_ECC_CURVE TPM_ECC_SM2_P256 = 0x0020;
+const TPM_CC TPM_CC_FIRST = 0x0000011F;
+const TPM_CC TPM_CC_PP_FIRST = 0x0000011F;
+const TPM_CC TPM_CC_NV_UndefineSpaceSpecial = 0x0000011F;
+const TPM_CC TPM_CC_EvictControl = 0x00000120;
+const TPM_CC TPM_CC_HierarchyControl = 0x00000121;
+const TPM_CC TPM_CC_NV_UndefineSpace = 0x00000122;
+const TPM_CC TPM_CC_ChangeEPS = 0x00000124;
+const TPM_CC TPM_CC_ChangePPS = 0x00000125;
+const TPM_CC TPM_CC_Clear = 0x00000126;
+const TPM_CC TPM_CC_ClearControl = 0x00000127;
+const TPM_CC TPM_CC_ClockSet = 0x00000128;
+const TPM_CC TPM_CC_HierarchyChangeAuth = 0x00000129;
+const TPM_CC TPM_CC_NV_DefineSpace = 0x0000012A;
+const TPM_CC TPM_CC_PCR_Allocate = 0x0000012B;
+const TPM_CC TPM_CC_PCR_SetAuthPolicy = 0x0000012C;
+const TPM_CC TPM_CC_PP_Commands = 0x0000012D;
+const TPM_CC TPM_CC_SetPrimaryPolicy = 0x0000012E;
+const TPM_CC TPM_CC_FieldUpgradeStart = 0x0000012F;
+const TPM_CC TPM_CC_ClockRateAdjust = 0x00000130;
+const TPM_CC TPM_CC_CreatePrimary = 0x00000131;
+const TPM_CC TPM_CC_NV_GlobalWriteLock = 0x00000132;
+const TPM_CC TPM_CC_PP_LAST = 0x00000132;
+const TPM_CC TPM_CC_GetCommandAuditDigest = 0x00000133;
+const TPM_CC TPM_CC_NV_Increment = 0x00000134;
+const TPM_CC TPM_CC_NV_SetBits = 0x00000135;
+const TPM_CC TPM_CC_NV_Extend = 0x00000136;
+const TPM_CC TPM_CC_NV_Write = 0x00000137;
+const TPM_CC TPM_CC_NV_WriteLock = 0x00000138;
+const TPM_CC TPM_CC_DictionaryAttackLockReset = 0x00000139;
+const TPM_CC TPM_CC_DictionaryAttackParameters = 0x0000013A;
+const TPM_CC TPM_CC_NV_ChangeAuth = 0x0000013B;
+const TPM_CC TPM_CC_PCR_Event = 0x0000013C;
+const TPM_CC TPM_CC_PCR_Reset = 0x0000013D;
+const TPM_CC TPM_CC_SequenceComplete = 0x0000013E;
+const TPM_CC TPM_CC_SetAlgorithmSet = 0x0000013F;
+const TPM_CC TPM_CC_SetCommandCodeAuditStatus = 0x00000140;
+const TPM_CC TPM_CC_FieldUpgradeData = 0x00000141;
+const TPM_CC TPM_CC_IncrementalSelfTest = 0x00000142;
+const TPM_CC TPM_CC_SelfTest = 0x00000143;
+const TPM_CC TPM_CC_Startup = 0x00000144;
+const TPM_CC TPM_CC_Shutdown = 0x00000145;
+const TPM_CC TPM_CC_StirRandom = 0x00000146;
+const TPM_CC TPM_CC_ActivateCredential = 0x00000147;
+const TPM_CC TPM_CC_Certify = 0x00000148;
+const TPM_CC TPM_CC_PolicyNV = 0x00000149;
+const TPM_CC TPM_CC_CertifyCreation = 0x0000014A;
+const TPM_CC TPM_CC_Duplicate = 0x0000014B;
+const TPM_CC TPM_CC_GetTime = 0x0000014C;
+const TPM_CC TPM_CC_GetSessionAuditDigest = 0x0000014D;
+const TPM_CC TPM_CC_NV_Read = 0x0000014E;
+const TPM_CC TPM_CC_NV_ReadLock = 0x0000014F;
+const TPM_CC TPM_CC_ObjectChangeAuth = 0x00000150;
+const TPM_CC TPM_CC_PolicySecret = 0x00000151;
+const TPM_CC TPM_CC_Rewrap = 0x00000152;
+const TPM_CC TPM_CC_Create = 0x00000153;
+const TPM_CC TPM_CC_ECDH_ZGen = 0x00000154;
+const TPM_CC TPM_CC_HMAC = 0x00000155;
+const TPM_CC TPM_CC_Import = 0x00000156;
+const TPM_CC TPM_CC_Load = 0x00000157;
+const TPM_CC TPM_CC_Quote = 0x00000158;
+const TPM_CC TPM_CC_RSA_Decrypt = 0x00000159;
+const TPM_CC TPM_CC_HMAC_Start = 0x0000015B;
+const TPM_CC TPM_CC_SequenceUpdate = 0x0000015C;
+const TPM_CC TPM_CC_Sign = 0x0000015D;
+const TPM_CC TPM_CC_Unseal = 0x0000015E;
+const TPM_CC TPM_CC_PolicySigned = 0x00000160;
+const TPM_CC TPM_CC_ContextLoad = 0x00000161;
+const TPM_CC TPM_CC_ContextSave = 0x00000162;
+const TPM_CC TPM_CC_ECDH_KeyGen = 0x00000163;
+const TPM_CC TPM_CC_EncryptDecrypt = 0x00000164;
+const TPM_CC TPM_CC_FlushContext = 0x00000165;
+const TPM_CC TPM_CC_LoadExternal = 0x00000167;
+const TPM_CC TPM_CC_MakeCredential = 0x00000168;
+const TPM_CC TPM_CC_NV_ReadPublic = 0x00000169;
+const TPM_CC TPM_CC_PolicyAuthorize = 0x0000016A;
+const TPM_CC TPM_CC_PolicyAuthValue = 0x0000016B;
+const TPM_CC TPM_CC_PolicyCommandCode = 0x0000016C;
+const TPM_CC TPM_CC_PolicyCounterTimer = 0x0000016D;
+const TPM_CC TPM_CC_PolicyCpHash = 0x0000016E;
+const TPM_CC TPM_CC_PolicyLocality = 0x0000016F;
+const TPM_CC TPM_CC_PolicyNameHash = 0x00000170;
+const TPM_CC TPM_CC_PolicyOR = 0x00000171;
+const TPM_CC TPM_CC_PolicyTicket = 0x00000172;
+const TPM_CC TPM_CC_ReadPublic = 0x00000173;
+const TPM_CC TPM_CC_RSA_Encrypt = 0x00000174;
+const TPM_CC TPM_CC_StartAuthSession = 0x00000176;
+const TPM_CC TPM_CC_VerifySignature = 0x00000177;
+const TPM_CC TPM_CC_ECC_Parameters = 0x00000178;
+const TPM_CC TPM_CC_FirmwareRead = 0x00000179;
+const TPM_CC TPM_CC_GetCapability = 0x0000017A;
+const TPM_CC TPM_CC_GetRandom = 0x0000017B;
+const TPM_CC TPM_CC_GetTestResult = 0x0000017C;
+const TPM_CC TPM_CC_Hash = 0x0000017D;
+const TPM_CC TPM_CC_PCR_Read = 0x0000017E;
+const TPM_CC TPM_CC_PolicyPCR = 0x0000017F;
+const TPM_CC TPM_CC_PolicyRestart = 0x00000180;
+const TPM_CC TPM_CC_ReadClock = 0x00000181;
+const TPM_CC TPM_CC_PCR_Extend = 0x00000182;
+const TPM_CC TPM_CC_PCR_SetAuthValue = 0x00000183;
+const TPM_CC TPM_CC_NV_Certify = 0x00000184;
+const TPM_CC TPM_CC_EventSequenceComplete = 0x00000185;
+const TPM_CC TPM_CC_HashSequenceStart = 0x00000186;
+const TPM_CC TPM_CC_PolicyPhysicalPresence = 0x00000187;
+const TPM_CC TPM_CC_PolicyDuplicationSelect = 0x00000188;
+const TPM_CC TPM_CC_PolicyGetDigest = 0x00000189;
+const TPM_CC TPM_CC_TestParms = 0x0000018A;
+const TPM_CC TPM_CC_Commit = 0x0000018B;
+const TPM_CC TPM_CC_PolicyPassword = 0x0000018C;
+const TPM_CC TPM_CC_ZGen_2Phase = 0x0000018D;
+const TPM_CC TPM_CC_EC_Ephemeral = 0x0000018E;
+const TPM_CC TPM_CC_PolicyNvWritten = 0x0000018F;
+const TPM_CC TPM_CC_LAST = 0x0000018F;
+const TPM_RC TPM_RC_SUCCESS = 0x000;
+const TPM_RC TPM_RC_BAD_TAG = 0x01E;
+const TPM_RC RC_VER1 = 0x100;
+const TPM_RC TPM_RC_INITIALIZE = RC_VER1 + 0x000;
+const TPM_RC TPM_RC_FAILURE = RC_VER1 + 0x001;
+const TPM_RC TPM_RC_SEQUENCE = RC_VER1 + 0x003;
+const TPM_RC TPM_RC_PRIVATE = RC_VER1 + 0x00B;
+const TPM_RC TPM_RC_HMAC = RC_VER1 + 0x019;
+const TPM_RC TPM_RC_DISABLED = RC_VER1 + 0x020;
+const TPM_RC TPM_RC_EXCLUSIVE = RC_VER1 + 0x021;
+const TPM_RC TPM_RC_AUTH_TYPE = RC_VER1 + 0x024;
+const TPM_RC TPM_RC_AUTH_MISSING = RC_VER1 + 0x025;
+const TPM_RC TPM_RC_POLICY = RC_VER1 + 0x026;
+const TPM_RC TPM_RC_PCR = RC_VER1 + 0x027;
+const TPM_RC TPM_RC_PCR_CHANGED = RC_VER1 + 0x028;
+const TPM_RC TPM_RC_UPGRADE = RC_VER1 + 0x02D;
+const TPM_RC TPM_RC_TOO_MANY_CONTEXTS = RC_VER1 + 0x02E;
+const TPM_RC TPM_RC_AUTH_UNAVAILABLE = RC_VER1 + 0x02F;
+const TPM_RC TPM_RC_REBOOT = RC_VER1 + 0x030;
+const TPM_RC TPM_RC_UNBALANCED = RC_VER1 + 0x031;
+const TPM_RC TPM_RC_COMMAND_SIZE = RC_VER1 + 0x042;
+const TPM_RC TPM_RC_COMMAND_CODE = RC_VER1 + 0x043;
+const TPM_RC TPM_RC_AUTHSIZE = RC_VER1 + 0x044;
+const TPM_RC TPM_RC_AUTH_CONTEXT = RC_VER1 + 0x045;
+const TPM_RC TPM_RC_NV_RANGE = RC_VER1 + 0x046;
+const TPM_RC TPM_RC_NV_SIZE = RC_VER1 + 0x047;
+const TPM_RC TPM_RC_NV_LOCKED = RC_VER1 + 0x048;
+const TPM_RC TPM_RC_NV_AUTHORIZATION = RC_VER1 + 0x049;
+const TPM_RC TPM_RC_NV_UNINITIALIZED = RC_VER1 + 0x04A;
+const TPM_RC TPM_RC_NV_SPACE = RC_VER1 + 0x04B;
+const TPM_RC TPM_RC_NV_DEFINED = RC_VER1 + 0x04C;
+const TPM_RC TPM_RC_BAD_CONTEXT = RC_VER1 + 0x050;
+const TPM_RC TPM_RC_CPHASH = RC_VER1 + 0x051;
+const TPM_RC TPM_RC_PARENT = RC_VER1 + 0x052;
+const TPM_RC TPM_RC_NEEDS_TEST = RC_VER1 + 0x053;
+const TPM_RC TPM_RC_NO_RESULT = RC_VER1 + 0x054;
+const TPM_RC TPM_RC_SENSITIVE = RC_VER1 + 0x055;
+const TPM_RC RC_MAX_FM0 = RC_VER1 + 0x07F;
+const TPM_RC RC_FMT1 = 0x080;
+const TPM_RC TPM_RC_ASYMMETRIC = RC_FMT1 + 0x001;
+const TPM_RC TPM_RC_ATTRIBUTES = RC_FMT1 + 0x002;
+const TPM_RC TPM_RC_HASH = RC_FMT1 + 0x003;
+const TPM_RC TPM_RC_VALUE = RC_FMT1 + 0x004;
+const TPM_RC TPM_RC_HIERARCHY = RC_FMT1 + 0x005;
+const TPM_RC TPM_RC_KEY_SIZE = RC_FMT1 + 0x007;
+const TPM_RC TPM_RC_MGF = RC_FMT1 + 0x008;
+const TPM_RC TPM_RC_MODE = RC_FMT1 + 0x009;
+const TPM_RC TPM_RC_TYPE = RC_FMT1 + 0x00A;
+const TPM_RC TPM_RC_HANDLE = RC_FMT1 + 0x00B;
+const TPM_RC TPM_RC_KDF = RC_FMT1 + 0x00C;
+const TPM_RC TPM_RC_RANGE = RC_FMT1 + 0x00D;
+const TPM_RC TPM_RC_AUTH_FAIL = RC_FMT1 + 0x00E;
+const TPM_RC TPM_RC_NONCE = RC_FMT1 + 0x00F;
+const TPM_RC TPM_RC_PP = RC_FMT1 + 0x010;
+const TPM_RC TPM_RC_SCHEME = RC_FMT1 + 0x012;
+const TPM_RC TPM_RC_SIZE = RC_FMT1 + 0x015;
+const TPM_RC TPM_RC_SYMMETRIC = RC_FMT1 + 0x016;
+const TPM_RC TPM_RC_TAG = RC_FMT1 + 0x017;
+const TPM_RC TPM_RC_SELECTOR = RC_FMT1 + 0x018;
+const TPM_RC TPM_RC_INSUFFICIENT = RC_FMT1 + 0x01A;
+const TPM_RC TPM_RC_SIGNATURE = RC_FMT1 + 0x01B;
+const TPM_RC TPM_RC_KEY = RC_FMT1 + 0x01C;
+const TPM_RC TPM_RC_POLICY_FAIL = RC_FMT1 + 0x01D;
+const TPM_RC TPM_RC_INTEGRITY = RC_FMT1 + 0x01F;
+const TPM_RC TPM_RC_TICKET = RC_FMT1 + 0x020;
+const TPM_RC TPM_RC_RESERVED_BITS = RC_FMT1 + 0x021;
+const TPM_RC TPM_RC_BAD_AUTH = RC_FMT1 + 0x022;
+const TPM_RC TPM_RC_EXPIRED = RC_FMT1 + 0x023;
+const TPM_RC TPM_RC_POLICY_CC = RC_FMT1 + 0x024;
+const TPM_RC TPM_RC_BINDING = RC_FMT1 + 0x025;
+const TPM_RC TPM_RC_CURVE = RC_FMT1 + 0x026;
+const TPM_RC TPM_RC_ECC_POINT = RC_FMT1 + 0x027;
+const TPM_RC RC_WARN = 0x900;
+const TPM_RC TPM_RC_CONTEXT_GAP = RC_WARN + 0x001;
+const TPM_RC TPM_RC_OBJECT_MEMORY = RC_WARN + 0x002;
+const TPM_RC TPM_RC_SESSION_MEMORY = RC_WARN + 0x003;
+const TPM_RC TPM_RC_MEMORY = RC_WARN + 0x004;
+const TPM_RC TPM_RC_SESSION_HANDLES = RC_WARN + 0x005;
+const TPM_RC TPM_RC_OBJECT_HANDLES = RC_WARN + 0x006;
+const TPM_RC TPM_RC_LOCALITY = RC_WARN + 0x007;
+const TPM_RC TPM_RC_YIELDED = RC_WARN + 0x008;
+const TPM_RC TPM_RC_CANCELED = RC_WARN + 0x009;
+const TPM_RC TPM_RC_TESTING = RC_WARN + 0x00A;
+const TPM_RC TPM_RC_REFERENCE_H0 = RC_WARN + 0x010;
+const TPM_RC TPM_RC_REFERENCE_H1 = RC_WARN + 0x011;
+const TPM_RC TPM_RC_REFERENCE_H2 = RC_WARN + 0x012;
+const TPM_RC TPM_RC_REFERENCE_H3 = RC_WARN + 0x013;
+const TPM_RC TPM_RC_REFERENCE_H4 = RC_WARN + 0x014;
+const TPM_RC TPM_RC_REFERENCE_H5 = RC_WARN + 0x015;
+const TPM_RC TPM_RC_REFERENCE_H6 = RC_WARN + 0x016;
+const TPM_RC TPM_RC_REFERENCE_S0 = RC_WARN + 0x018;
+const TPM_RC TPM_RC_REFERENCE_S1 = RC_WARN + 0x019;
+const TPM_RC TPM_RC_REFERENCE_S2 = RC_WARN + 0x01A;
+const TPM_RC TPM_RC_REFERENCE_S3 = RC_WARN + 0x01B;
+const TPM_RC TPM_RC_REFERENCE_S4 = RC_WARN + 0x01C;
+const TPM_RC TPM_RC_REFERENCE_S5 = RC_WARN + 0x01D;
+const TPM_RC TPM_RC_REFERENCE_S6 = RC_WARN + 0x01E;
+const TPM_RC TPM_RC_NV_RATE = RC_WARN + 0x020;
+const TPM_RC TPM_RC_LOCKOUT = RC_WARN + 0x021;
+const TPM_RC TPM_RC_RETRY = RC_WARN + 0x022;
+const TPM_RC TPM_RC_NV_UNAVAILABLE = RC_WARN + 0x023;
+const TPM_RC TPM_RC_NOT_USED = RC_WARN + 0x7F;
+const TPM_RC TPM_RC_H = 0x000;
+const TPM_RC TPM_RC_P = 0x040;
+const TPM_RC TPM_RC_S = 0x800;
+const TPM_RC TPM_RC_1 = 0x100;
+const TPM_RC TPM_RC_2 = 0x200;
+const TPM_RC TPM_RC_3 = 0x300;
+const TPM_RC TPM_RC_4 = 0x400;
+const TPM_RC TPM_RC_5 = 0x500;
+const TPM_RC TPM_RC_6 = 0x600;
+const TPM_RC TPM_RC_7 = 0x700;
+const TPM_RC TPM_RC_8 = 0x800;
+const TPM_RC TPM_RC_9 = 0x900;
+const TPM_RC TPM_RC_A = 0xA00;
+const TPM_RC TPM_RC_B = 0xB00;
+const TPM_RC TPM_RC_C = 0xC00;
+const TPM_RC TPM_RC_D = 0xD00;
+const TPM_RC TPM_RC_E = 0xE00;
+const TPM_RC TPM_RC_F = 0xF00;
+const TPM_RC TPM_RC_N_MASK = 0xF00;
+const TPM_CLOCK_ADJUST TPM_CLOCK_COARSE_SLOWER = -3;
+const TPM_CLOCK_ADJUST TPM_CLOCK_MEDIUM_SLOWER = -2;
+const TPM_CLOCK_ADJUST TPM_CLOCK_FINE_SLOWER = -1;
+const TPM_CLOCK_ADJUST TPM_CLOCK_NO_CHANGE = 0;
+const TPM_CLOCK_ADJUST TPM_CLOCK_FINE_FASTER = 1;
+const TPM_CLOCK_ADJUST TPM_CLOCK_MEDIUM_FASTER = 2;
+const TPM_CLOCK_ADJUST TPM_CLOCK_COARSE_FASTER = 3;
+const TPM_EO TPM_EO_EQ = 0x0000;
+const TPM_EO TPM_EO_NEQ = 0x0001;
+const TPM_EO TPM_EO_SIGNED_GT = 0x0002;
+const TPM_EO TPM_EO_UNSIGNED_GT = 0x0003;
+const TPM_EO TPM_EO_SIGNED_LT = 0x0004;
+const TPM_EO TPM_EO_UNSIGNED_LT = 0x0005;
+const TPM_EO TPM_EO_SIGNED_GE = 0x0006;
+const TPM_EO TPM_EO_UNSIGNED_GE = 0x0007;
+const TPM_EO TPM_EO_SIGNED_LE = 0x0008;
+const TPM_EO TPM_EO_UNSIGNED_LE = 0x0009;
+const TPM_EO TPM_EO_BITSET = 0x000A;
+const TPM_EO TPM_EO_BITCLEAR = 0x000B;
+const TPM_ST TPM_ST_RSP_COMMAND = 0x00C4;
+const TPM_ST TPM_ST_NULL = 0X8000;
+const TPM_ST TPM_ST_NO_SESSIONS = 0x8001;
+const TPM_ST TPM_ST_SESSIONS = 0x8002;
+const TPM_ST TPM_ST_ATTEST_NV = 0x8014;
+const TPM_ST TPM_ST_ATTEST_COMMAND_AUDIT = 0x8015;
+const TPM_ST TPM_ST_ATTEST_SESSION_AUDIT = 0x8016;
+const TPM_ST TPM_ST_ATTEST_CERTIFY = 0x8017;
+const TPM_ST TPM_ST_ATTEST_QUOTE = 0x8018;
+const TPM_ST TPM_ST_ATTEST_TIME = 0x8019;
+const TPM_ST TPM_ST_ATTEST_CREATION = 0x801A;
+const TPM_ST TPM_ST_CREATION = 0x8021;
+const TPM_ST TPM_ST_VERIFIED = 0x8022;
+const TPM_ST TPM_ST_AUTH_SECRET = 0x8023;
+const TPM_ST TPM_ST_HASHCHECK = 0x8024;
+const TPM_ST TPM_ST_AUTH_SIGNED = 0x8025;
+const TPM_ST TPM_ST_FU_MANIFEST = 0x8029;
+const TPM_SU TPM_SU_CLEAR = 0x0000;
+const TPM_SU TPM_SU_STATE = 0x0001;
+const TPM_SE TPM_SE_HMAC = 0x00;
+const TPM_SE TPM_SE_POLICY = 0x01;
+const TPM_SE TPM_SE_TRIAL = 0x03;
+const TPM_CAP TPM_CAP_FIRST = 0x00000000;
+const TPM_CAP TPM_CAP_ALGS = 0x00000000;
+const TPM_CAP TPM_CAP_HANDLES = 0x00000001;
+const TPM_CAP TPM_CAP_COMMANDS = 0x00000002;
+const TPM_CAP TPM_CAP_PP_COMMANDS = 0x00000003;
+const TPM_CAP TPM_CAP_AUDIT_COMMANDS = 0x00000004;
+const TPM_CAP TPM_CAP_PCRS = 0x00000005;
+const TPM_CAP TPM_CAP_TPM_PROPERTIES = 0x00000006;
+const TPM_CAP TPM_CAP_PCR_PROPERTIES = 0x00000007;
+const TPM_CAP TPM_CAP_ECC_CURVES = 0x00000008;
+const TPM_CAP TPM_CAP_LAST = 0x00000008;
+const TPM_CAP TPM_CAP_VENDOR_PROPERTY = 0x00000100;
+const TPM_PT TPM_PT_NONE = 0x00000000;
+const TPM_PT PT_GROUP = 0x00000100;
+const TPM_PT PT_FIXED = PT_GROUP * 1;
+const TPM_PT TPM_PT_FAMILY_INDICATOR = PT_FIXED + 0;
+const TPM_PT TPM_PT_LEVEL = PT_FIXED + 1;
+const TPM_PT TPM_PT_REVISION = PT_FIXED + 2;
+const TPM_PT TPM_PT_DAY_OF_YEAR = PT_FIXED + 3;
+const TPM_PT TPM_PT_YEAR = PT_FIXED + 4;
+const TPM_PT TPM_PT_MANUFACTURER = PT_FIXED + 5;
+const TPM_PT TPM_PT_VENDOR_STRING_1 = PT_FIXED + 6;
+const TPM_PT TPM_PT_VENDOR_STRING_2 = PT_FIXED + 7;
+const TPM_PT TPM_PT_VENDOR_STRING_3 = PT_FIXED + 8;
+const TPM_PT TPM_PT_VENDOR_STRING_4 = PT_FIXED + 9;
+const TPM_PT TPM_PT_VENDOR_TPM_TYPE = PT_FIXED + 10;
+const TPM_PT TPM_PT_FIRMWARE_VERSION_1 = PT_FIXED + 11;
+const TPM_PT TPM_PT_FIRMWARE_VERSION_2 = PT_FIXED + 12;
+const TPM_PT TPM_PT_INPUT_BUFFER = PT_FIXED + 13;
+const TPM_PT TPM_PT_HR_TRANSIENT_MIN = PT_FIXED + 14;
+const TPM_PT TPM_PT_HR_PERSISTENT_MIN = PT_FIXED + 15;
+const TPM_PT TPM_PT_HR_LOADED_MIN = PT_FIXED + 16;
+const TPM_PT TPM_PT_ACTIVE_SESSIONS_MAX = PT_FIXED + 17;
+const TPM_PT TPM_PT_PCR_COUNT = PT_FIXED + 18;
+const TPM_PT TPM_PT_PCR_SELECT_MIN = PT_FIXED + 19;
+const TPM_PT TPM_PT_CONTEXT_GAP_MAX = PT_FIXED + 20;
+const TPM_PT TPM_PT_NV_COUNTERS_MAX = PT_FIXED + 22;
+const TPM_PT TPM_PT_NV_INDEX_MAX = PT_FIXED + 23;
+const TPM_PT TPM_PT_MEMORY = PT_FIXED + 24;
+const TPM_PT TPM_PT_CLOCK_UPDATE = PT_FIXED + 25;
+const TPM_PT TPM_PT_CONTEXT_HASH = PT_FIXED + 26;
+const TPM_PT TPM_PT_CONTEXT_SYM = PT_FIXED + 27;
+const TPM_PT TPM_PT_CONTEXT_SYM_SIZE = PT_FIXED + 28;
+const TPM_PT TPM_PT_ORDERLY_COUNT = PT_FIXED + 29;
+const TPM_PT TPM_PT_MAX_COMMAND_SIZE = PT_FIXED + 30;
+const TPM_PT TPM_PT_MAX_RESPONSE_SIZE = PT_FIXED + 31;
+const TPM_PT TPM_PT_MAX_DIGEST = PT_FIXED + 32;
+const TPM_PT TPM_PT_MAX_OBJECT_CONTEXT = PT_FIXED + 33;
+const TPM_PT TPM_PT_MAX_SESSION_CONTEXT = PT_FIXED + 34;
+const TPM_PT TPM_PT_PS_FAMILY_INDICATOR = PT_FIXED + 35;
+const TPM_PT TPM_PT_PS_LEVEL = PT_FIXED + 36;
+const TPM_PT TPM_PT_PS_REVISION = PT_FIXED + 37;
+const TPM_PT TPM_PT_PS_DAY_OF_YEAR = PT_FIXED + 38;
+const TPM_PT TPM_PT_PS_YEAR = PT_FIXED + 39;
+const TPM_PT TPM_PT_SPLIT_MAX = PT_FIXED + 40;
+const TPM_PT TPM_PT_TOTAL_COMMANDS = PT_FIXED + 41;
+const TPM_PT TPM_PT_LIBRARY_COMMANDS = PT_FIXED + 42;
+const TPM_PT TPM_PT_VENDOR_COMMANDS = PT_FIXED + 43;
+const TPM_PT TPM_PT_NV_BUFFER_MAX = PT_FIXED + 44;
+const TPM_PT PT_VAR = PT_GROUP * 2;
+const TPM_PT TPM_PT_PERMANENT = PT_VAR + 0;
+const TPM_PT TPM_PT_STARTUP_CLEAR = PT_VAR + 1;
+const TPM_PT TPM_PT_HR_NV_INDEX = PT_VAR + 2;
+const TPM_PT TPM_PT_HR_LOADED = PT_VAR + 3;
+const TPM_PT TPM_PT_HR_LOADED_AVAIL = PT_VAR + 4;
+const TPM_PT TPM_PT_HR_ACTIVE = PT_VAR + 5;
+const TPM_PT TPM_PT_HR_ACTIVE_AVAIL = PT_VAR + 6;
+const TPM_PT TPM_PT_HR_TRANSIENT_AVAIL = PT_VAR + 7;
+const TPM_PT TPM_PT_HR_PERSISTENT = PT_VAR + 8;
+const TPM_PT TPM_PT_HR_PERSISTENT_AVAIL = PT_VAR + 9;
+const TPM_PT TPM_PT_NV_COUNTERS = PT_VAR + 10;
+const TPM_PT TPM_PT_NV_COUNTERS_AVAIL = PT_VAR + 11;
+const TPM_PT TPM_PT_ALGORITHM_SET = PT_VAR + 12;
+const TPM_PT TPM_PT_LOADED_CURVES = PT_VAR + 13;
+const TPM_PT TPM_PT_LOCKOUT_COUNTER = PT_VAR + 14;
+const TPM_PT TPM_PT_MAX_AUTH_FAIL = PT_VAR + 15;
+const TPM_PT TPM_PT_LOCKOUT_INTERVAL = PT_VAR + 16;
+const TPM_PT TPM_PT_LOCKOUT_RECOVERY = PT_VAR + 17;
+const TPM_PT TPM_PT_NV_WRITE_RECOVERY = PT_VAR + 18;
+const TPM_PT TPM_PT_AUDIT_COUNTER_0 = PT_VAR + 19;
+const TPM_PT TPM_PT_AUDIT_COUNTER_1 = PT_VAR + 20;
+const TPM_PT_PCR TPM_PT_PCR_FIRST = 0x00000000;
+const TPM_PT_PCR TPM_PT_PCR_SAVE = 0x00000000;
+const TPM_PT_PCR TPM_PT_PCR_EXTEND_L0 = 0x00000001;
+const TPM_PT_PCR TPM_PT_PCR_RESET_L0 = 0x00000002;
+const TPM_PT_PCR TPM_PT_PCR_EXTEND_L1 = 0x00000003;
+const TPM_PT_PCR TPM_PT_PCR_RESET_L1 = 0x00000004;
+const TPM_PT_PCR TPM_PT_PCR_EXTEND_L2 = 0x00000005;
+const TPM_PT_PCR TPM_PT_PCR_RESET_L2 = 0x00000006;
+const TPM_PT_PCR TPM_PT_PCR_EXTEND_L3 = 0x00000007;
+const TPM_PT_PCR TPM_PT_PCR_RESET_L3 = 0x00000008;
+const TPM_PT_PCR TPM_PT_PCR_EXTEND_L4 = 0x00000009;
+const TPM_PT_PCR TPM_PT_PCR_RESET_L4 = 0x0000000A;
+const TPM_PT_PCR TPM_PT_PCR_NO_INCREMENT = 0x00000011;
+const TPM_PT_PCR TPM_PT_PCR_DRTM_RESET = 0x00000012;
+const TPM_PT_PCR TPM_PT_PCR_POLICY = 0x00000013;
+const TPM_PT_PCR TPM_PT_PCR_AUTH = 0x00000014;
+const TPM_PT_PCR TPM_PT_PCR_LAST = 0x00000014;
+const TPM_PS TPM_PS_MAIN = 0x00000000;
+const TPM_PS TPM_PS_PC = 0x00000001;
+const TPM_PS TPM_PS_PDA = 0x00000002;
+const TPM_PS TPM_PS_CELL_PHONE = 0x00000003;
+const TPM_PS TPM_PS_SERVER = 0x00000004;
+const TPM_PS TPM_PS_PERIPHERAL = 0x00000005;
+const TPM_PS TPM_PS_TSS = 0x00000006;
+const TPM_PS TPM_PS_STORAGE = 0x00000007;
+const TPM_PS TPM_PS_AUTHENTICATION = 0x00000008;
+const TPM_PS TPM_PS_EMBEDDED = 0x00000009;
+const TPM_PS TPM_PS_HARDCOPY = 0x0000000A;
+const TPM_PS TPM_PS_INFRASTRUCTURE = 0x0000000B;
+const TPM_PS TPM_PS_VIRTUALIZATION = 0x0000000C;
+const TPM_PS TPM_PS_TNC = 0x0000000D;
+const TPM_PS TPM_PS_MULTI_TENANT = 0x0000000E;
+const TPM_PS TPM_PS_TC = 0x0000000F;
+const TPM_HT TPM_HT_PCR = 0x00;
+const TPM_HT TPM_HT_NV_INDEX = 0x01;
+const TPM_HT TPM_HT_HMAC_SESSION = 0x02;
+const TPM_HT TPM_HT_LOADED_SESSION = 0x02;
+const TPM_HT TPM_HT_POLICY_SESSION = 0x03;
+const TPM_HT TPM_HT_ACTIVE_SESSION = 0x03;
+const TPM_HT TPM_HT_PERMANENT = 0x40;
+const TPM_HT TPM_HT_TRANSIENT = 0x80;
+const TPM_HT TPM_HT_PERSISTENT = 0x81;
+const TPM_RH TPM_RH_FIRST = 0x40000000;
+const TPM_RH TPM_RH_SRK = 0x40000000;
+const TPM_RH TPM_RH_OWNER = 0x40000001;
+const TPM_RH TPM_RH_REVOKE = 0x40000002;
+const TPM_RH TPM_RH_TRANSPORT = 0x40000003;
+const TPM_RH TPM_RH_OPERATOR = 0x40000004;
+const TPM_RH TPM_RH_ADMIN = 0x40000005;
+const TPM_RH TPM_RH_EK = 0x40000006;
+const TPM_RH TPM_RH_NULL = 0x40000007;
+const TPM_RH TPM_RH_UNASSIGNED = 0x40000008;
+const TPM_RH TPM_RS_PW = 0x40000009;
+const TPM_RH TPM_RH_LOCKOUT = 0x4000000A;
+const TPM_RH TPM_RH_ENDORSEMENT = 0x4000000B;
+const TPM_RH TPM_RH_PLATFORM = 0x4000000C;
+const TPM_RH TPM_RH_PLATFORM_NV = 0x4000000D;
+const TPM_RH TPM_RH_LAST = 0x4000000D;
+const TPM_HC HR_HANDLE_MASK = 0x00FFFFFF;
+const TPM_HC HR_RANGE_MASK = 0xFF000000;
+const TPM_HC HR_SHIFT = 24;
+const TPM_HC HR_PCR = (TPM_HT_PCR << HR_SHIFT);
+const TPM_HC HR_HMAC_SESSION = (TPM_HT_HMAC_SESSION << HR_SHIFT);
+const TPM_HC HR_POLICY_SESSION = (TPM_HT_POLICY_SESSION << HR_SHIFT);
+const TPM_HC HR_TRANSIENT = (TPM_HT_TRANSIENT << HR_SHIFT);
+const TPM_HC HR_PERSISTENT = (TPM_HT_PERSISTENT << HR_SHIFT);
+const TPM_HC HR_NV_INDEX = (TPM_HT_NV_INDEX << HR_SHIFT);
+const TPM_HC HR_PERMANENT = (TPM_HT_PERMANENT << HR_SHIFT);
+const TPM_HC PCR_FIRST = (HR_PCR + 0);
+const TPM_HC PCR_LAST = (PCR_FIRST + IMPLEMENTATION_PCR-1);
+const TPM_HC HMAC_SESSION_FIRST = (HR_HMAC_SESSION + 0);
+const TPM_HC HMAC_SESSION_LAST = (HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1);
+const TPM_HC LOADED_SESSION_LAST = HMAC_SESSION_LAST;
+const TPM_HC POLICY_SESSION_FIRST = (HR_POLICY_SESSION + 0);
+const TPM_HC POLICY_SESSION_LAST = (POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1);
+const TPM_HC TRANSIENT_FIRST = (HR_TRANSIENT + 0);
+const TPM_HC ACTIVE_SESSION_FIRST = POLICY_SESSION_FIRST;
+const TPM_HC ACTIVE_SESSION_LAST = POLICY_SESSION_LAST;
+const TPM_HC TRANSIENT_LAST = (TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1);
+const TPM_HC PERSISTENT_FIRST = (HR_PERSISTENT + 0);
+const TPM_HC PERSISTENT_LAST = (PERSISTENT_FIRST + 0x00FFFFFF);
+const TPM_HC PLATFORM_PERSISTENT = (PERSISTENT_FIRST + 0x00800000);
+const TPM_HC NV_INDEX_FIRST = (HR_NV_INDEX + 0);
+const TPM_HC NV_INDEX_LAST = (NV_INDEX_FIRST + 0x00FFFFFF);
+const TPM_HC PERMANENT_FIRST = TPM_RH_FIRST;
+const TPM_HC PERMANENT_LAST = TPM_RH_LAST;
+
+struct TPMS_ALGORITHM_DESCRIPTION {
+ TPM_ALG_ID alg;
+ TPMA_ALGORITHM attributes;
+};
+
+union TPMU_HA {
+ BYTE sha1[SHA1_DIGEST_SIZE];
+ BYTE sha256[SHA256_DIGEST_SIZE];
+ BYTE sm3_256[SM3_256_DIGEST_SIZE];
+ BYTE sha384[SHA384_DIGEST_SIZE];
+ BYTE sha512[SHA512_DIGEST_SIZE];
+};
+
+struct TPMT_HA {
+ TPMI_ALG_HASH hash_alg;
+ TPMU_HA digest;
+};
+
+struct TPM2B_DIGEST {
+ UINT16 size;
+ BYTE buffer[sizeof(TPMU_HA)];
+};
+
+struct TPM2B_DATA {
+ UINT16 size;
+ BYTE buffer[sizeof(TPMT_HA)];
+};
+
+struct TPM2B_EVENT {
+ UINT16 size;
+ BYTE buffer[1024];
+};
+
+struct TPM2B_MAX_BUFFER {
+ UINT16 size;
+ BYTE buffer[MAX_DIGEST_BUFFER];
+};
+
+struct TPM2B_MAX_NV_BUFFER {
+ UINT16 size;
+ BYTE buffer[MAX_NV_BUFFER_SIZE];
+};
+
+struct TPM2B_TIMEOUT {
+ UINT16 size;
+ BYTE buffer[sizeof(UINT64)];
+};
+
+struct TPM2B_IV {
+ UINT16 size;
+ BYTE buffer[MAX_SYM_BLOCK_SIZE];
+};
+
+union TPMU_NAME {
+ TPMT_HA digest;
+ TPM_HANDLE handle;
+};
+
+struct TPM2B_NAME {
+ UINT16 size;
+ BYTE name[sizeof(TPMU_NAME)];
+};
+
+struct TPMS_PCR_SELECT {
+ UINT8 sizeof_select;
+ BYTE pcr_select[PCR_SELECT_MAX];
+};
+
+struct TPMS_PCR_SELECTION {
+ TPMI_ALG_HASH hash;
+ UINT8 sizeof_select;
+ BYTE pcr_select[PCR_SELECT_MAX];
+};
+
+struct TPMT_TK_CREATION {
+ TPM_ST tag;
+ TPMI_RH_HIERARCHY hierarchy;
+ TPM2B_DIGEST digest;
+};
+
+struct TPMT_TK_VERIFIED {
+ TPM_ST tag;
+ TPMI_RH_HIERARCHY hierarchy;
+ TPM2B_DIGEST digest;
+};
+
+struct TPMT_TK_AUTH {
+ TPMI_RH_HIERARCHY hierarchy;
+ TPM2B_DIGEST digest;
+};
+
+struct TPMT_TK_HASHCHECK {
+ TPM_ST tag;
+ TPMI_RH_HIERARCHY hierarchy;
+ TPM2B_DIGEST digest;
+};
+
+struct TPMS_ALG_PROPERTY {
+ TPM_ALG_ID alg;
+ TPMA_ALGORITHM alg_properties;
+};
+
+struct TPMS_TAGGED_PROPERTY {
+ TPM_PT property;
+ UINT32 value;
+};
+
+struct TPMS_TAGGED_PCR_SELECT {
+ TPM_PT tag;
+ UINT8 sizeof_select;
+ BYTE pcr_select[PCR_SELECT_MAX];
+};
+
+struct TPML_CC {
+ UINT32 count;
+ TPM_CC command_codes[MAX_CAP_CC];
+};
+
+struct TPML_CCA {
+ UINT32 count;
+ TPMA_CC command_attributes[MAX_CAP_CC];
+};
+
+struct TPML_ALG {
+ UINT32 count;
+ TPM_ALG_ID algorithms[MAX_ALG_LIST_SIZE];
+};
+
+struct TPML_HANDLE {
+ UINT32 count;
+ TPM_HANDLE handle[MAX_CAP_HANDLES];
+};
+
+struct TPML_DIGEST {
+ UINT32 count;
+ TPM2B_DIGEST digests[8];
+};
+
+struct TPML_DIGEST_VALUES {
+ UINT32 count;
+ TPMT_HA digests[HASH_COUNT];
+};
+
+struct TPM2B_DIGEST_VALUES {
+ UINT16 size;
+ BYTE buffer[sizeof(TPML_DIGEST_VALUES)];
+};
+
+struct TPML_PCR_SELECTION {
+ UINT32 count;
+ TPMS_PCR_SELECTION pcr_selections[HASH_COUNT];
+};
+
+struct TPML_ALG_PROPERTY {
+ UINT32 count;
+ TPMS_ALG_PROPERTY alg_properties[MAX_CAP_ALGS];
+};
+
+struct TPML_TAGGED_TPM_PROPERTY {
+ UINT32 count;
+ TPMS_TAGGED_PROPERTY tpm_property[MAX_TPM_PROPERTIES];
+};
+
+struct TPML_TAGGED_PCR_PROPERTY {
+ UINT32 count;
+ TPMS_TAGGED_PCR_SELECT pcr_property[MAX_PCR_PROPERTIES];
+};
+
+struct TPML_ECC_CURVE {
+ UINT32 count;
+ TPM_ECC_CURVE ecc_curves[MAX_ECC_CURVES];
+};
+
+union TPMU_CAPABILITIES {
+ TPML_ALG_PROPERTY algorithms;
+ TPML_HANDLE handles;
+ TPML_CCA command;
+ TPML_CC pp_commands;
+ TPML_CC audit_commands;
+ TPML_PCR_SELECTION assigned_pcr;
+ TPML_TAGGED_TPM_PROPERTY tpm_properties;
+ TPML_TAGGED_PCR_PROPERTY pcr_properties;
+ TPML_ECC_CURVE ecc_curves;
+};
+
+struct TPMS_CAPABILITY_DATA {
+ TPM_CAP capability;
+ TPMU_CAPABILITIES data;
+};
+
+struct TPMS_CLOCK_INFO {
+ UINT64 clock;
+ UINT32 reset_count;
+ UINT32 restart_count;
+ TPMI_YES_NO safe;
+};
+
+struct TPMS_TIME_INFO {
+ UINT64 time;
+ TPMS_CLOCK_INFO clock_info;
+};
+
+struct TPMS_TIME_ATTEST_INFO {
+ TPMS_TIME_INFO time;
+ UINT64 firmware_version;
+};
+
+struct TPMS_CERTIFY_INFO {
+ TPM2B_NAME name;
+ TPM2B_NAME qualified_name;
+};
+
+struct TPMS_QUOTE_INFO {
+ TPML_PCR_SELECTION pcr_select;
+ TPM2B_DIGEST pcr_digest;
+};
+
+struct TPMS_COMMAND_AUDIT_INFO {
+ UINT64 audit_counter;
+ TPM_ALG_ID digest_alg;
+ TPM2B_DIGEST audit_digest;
+ TPM2B_DIGEST command_digest;
+};
+
+struct TPMS_SESSION_AUDIT_INFO {
+ TPMI_YES_NO exclusive_session;
+ TPM2B_DIGEST session_digest;
+};
+
+struct TPMS_CREATION_INFO {
+ TPM2B_NAME object_name;
+ TPM2B_DIGEST creation_hash;
+};
+
+struct TPMS_NV_CERTIFY_INFO {
+ TPM2B_NAME index_name;
+ UINT16 offset;
+ TPM2B_MAX_NV_BUFFER nv_contents;
+};
+
+union TPMU_ATTEST {
+ TPMS_CERTIFY_INFO certify;
+ TPMS_CREATION_INFO creation;
+ TPMS_QUOTE_INFO quote;
+ TPMS_COMMAND_AUDIT_INFO command_audit;
+ TPMS_SESSION_AUDIT_INFO session_audit;
+ TPMS_TIME_ATTEST_INFO time;
+ TPMS_NV_CERTIFY_INFO nv;
+};
+
+struct TPMS_ATTEST {
+ TPM_GENERATED magic;
+ TPMI_ST_ATTEST type;
+ TPM2B_NAME qualified_signer;
+ TPM2B_DATA extra_data;
+ TPMS_CLOCK_INFO clock_info;
+ UINT64 firmware_version;
+ TPMU_ATTEST attested;
+};
+
+struct TPM2B_ATTEST {
+ UINT16 size;
+ BYTE attestation_data[sizeof(TPMS_ATTEST)];
+};
+
+struct TPMS_AUTH_COMMAND {
+ TPMI_SH_AUTH_SESSION session_handle;
+ TPM2B_NONCE nonce;
+ TPMA_SESSION session_attributes;
+ TPM2B_AUTH hmac;
+};
+
+struct TPMS_AUTH_RESPONSE {
+ TPM2B_NONCE nonce;
+ TPMA_SESSION session_attributes;
+ TPM2B_AUTH hmac;
+};
+
+union TPMU_SYM_KEY_BITS {
+ TPMI_AES_KEY_BITS aes;
+ TPMI_SM4_KEY_BITS sm4;
+ TPM_KEY_BITS sym;
+ TPMI_ALG_HASH xor_;
+};
+
+union TPMU_SYM_MODE {
+ TPMI_ALG_SYM_MODE aes;
+ TPMI_ALG_SYM_MODE sm4;
+ TPMI_ALG_SYM_MODE sym;
+};
+
+union TPMU_SYM_DETAILS {
+};
+
+struct TPMT_SYM_DEF {
+ TPMI_ALG_SYM algorithm;
+ TPMU_SYM_KEY_BITS key_bits;
+ TPMU_SYM_MODE mode;
+ TPMU_SYM_DETAILS details;
+};
+
+struct TPMT_SYM_DEF_OBJECT {
+ TPMI_ALG_SYM_OBJECT algorithm;
+ TPMU_SYM_KEY_BITS key_bits;
+ TPMU_SYM_MODE mode;
+ TPMU_SYM_DETAILS details;
+};
+
+struct TPM2B_SYM_KEY {
+ UINT16 size;
+ BYTE buffer[MAX_SYM_KEY_BYTES];
+};
+
+struct TPMS_SYMCIPHER_PARMS {
+ TPMT_SYM_DEF_OBJECT sym;
+};
+
+struct TPM2B_SENSITIVE_DATA {
+ UINT16 size;
+ BYTE buffer[MAX_SYM_DATA];
+};
+
+struct TPMS_SENSITIVE_CREATE {
+ TPM2B_AUTH user_auth;
+ TPM2B_SENSITIVE_DATA data;
+};
+
+struct TPM2B_SENSITIVE_CREATE {
+ UINT16 size;
+ TPMS_SENSITIVE_CREATE sensitive;
+};
+
+struct TPMS_SCHEME_SIGHASH {
+ TPMI_ALG_HASH hash_alg;
+};
+
+struct TPMS_SCHEME_XOR {
+ TPMI_ALG_HASH hash_alg;
+ TPMI_ALG_KDF kdf;
+};
+
+union TPMU_SCHEME_KEYEDHASH {
+ TPMS_SCHEME_HMAC hmac;
+ TPMS_SCHEME_XOR xor_;
+};
+
+struct TPMT_KEYEDHASH_SCHEME {
+ TPMI_ALG_KEYEDHASH_SCHEME scheme;
+ TPMU_SCHEME_KEYEDHASH details;
+};
+
+struct TPMS_SCHEME_ECDAA {
+ TPMI_ALG_HASH hash_alg;
+ UINT16 count;
+};
+
+union TPMU_SIG_SCHEME {
+ TPMS_SCHEME_RSASSA rsassa;
+ TPMS_SCHEME_RSAPSS rsapss;
+ TPMS_SCHEME_ECDSA ecdsa;
+ TPMS_SCHEME_SM2 sm2;
+ TPMS_SCHEME_ECDAA ecdaa;
+ TPMS_SCHEME_ECSCHNORR ec_schnorr;
+ TPMS_SCHEME_HMAC hmac;
+ TPMS_SCHEME_SIGHASH any;
+};
+
+struct TPMT_SIG_SCHEME {
+ TPMI_ALG_SIG_SCHEME scheme;
+ TPMU_SIG_SCHEME details;
+};
+
+struct TPMS_SCHEME_OAEP {
+ TPMI_ALG_HASH hash_alg;
+};
+
+struct TPMS_SCHEME_ECDH {
+ TPMI_ALG_HASH hash_alg;
+};
+
+struct TPMS_SCHEME_MGF1 {
+ TPMI_ALG_HASH hash_alg;
+};
+
+struct TPMS_SCHEME_KDF1_SP800_56a {
+ TPMI_ALG_HASH hash_alg;
+};
+
+struct TPMS_SCHEME_KDF2 {
+ TPMI_ALG_HASH hash_alg;
+};
+
+struct TPMS_SCHEME_KDF1_SP800_108 {
+ TPMI_ALG_HASH hash_alg;
+};
+
+union TPMU_KDF_SCHEME {
+ TPMS_SCHEME_MGF1 mgf1;
+ TPMS_SCHEME_KDF1_SP800_56a kdf1_sp800_56a;
+ TPMS_SCHEME_KDF2 kdf2;
+ TPMS_SCHEME_KDF1_SP800_108 kdf1_sp800_108;
+};
+
+struct TPMT_KDF_SCHEME {
+ TPMI_ALG_KDF scheme;
+ TPMU_KDF_SCHEME details;
+};
+
+union TPMU_ASYM_SCHEME {
+ TPMS_SCHEME_RSASSA rsassa;
+ TPMS_SCHEME_RSAPSS rsapss;
+ TPMS_SCHEME_OAEP oaep;
+ TPMS_SCHEME_ECDSA ecdsa;
+ TPMS_SCHEME_SM2 sm2;
+ TPMS_SCHEME_ECDAA ecdaa;
+ TPMS_SCHEME_ECSCHNORR ec_schnorr;
+ TPMS_SCHEME_ECDH ecdh;
+ TPMS_SCHEME_SIGHASH any_sig;
+};
+
+struct TPMT_ASYM_SCHEME {
+ TPMI_ALG_ASYM_SCHEME scheme;
+ TPMU_ASYM_SCHEME details;
+};
+
+struct TPMT_RSA_SCHEME {
+ TPMI_ALG_RSA_SCHEME scheme;
+ TPMU_ASYM_SCHEME details;
+};
+
+struct TPMT_RSA_DECRYPT {
+ TPMI_ALG_RSA_DECRYPT scheme;
+ TPMU_ASYM_SCHEME details;
+};
+
+struct TPM2B_PUBLIC_KEY_RSA {
+ UINT16 size;
+ BYTE buffer[MAX_RSA_KEY_BYTES];
+};
+
+struct TPM2B_PRIVATE_KEY_RSA {
+ UINT16 size;
+ BYTE buffer[MAX_RSA_KEY_BYTES/2];
+};
+
+struct TPM2B_ECC_PARAMETER {
+ UINT16 size;
+ BYTE buffer[MAX_ECC_KEY_BYTES];
+};
+
+struct TPMS_ECC_POINT {
+ TPM2B_ECC_PARAMETER x;
+ TPM2B_ECC_PARAMETER y;
+};
+
+struct TPM2B_ECC_POINT {
+ UINT16 size;
+ TPMS_ECC_POINT point;
+};
+
+struct TPMT_ECC_SCHEME {
+ TPMI_ALG_ECC_SCHEME scheme;
+ TPMU_SIG_SCHEME details;
+};
+
+struct TPMS_ALGORITHM_DETAIL_ECC {
+ TPM_ECC_CURVE curve_id;
+ UINT16 key_size;
+ TPMT_KDF_SCHEME kdf;
+ TPMT_ECC_SCHEME sign;
+ TPM2B_ECC_PARAMETER p;
+ TPM2B_ECC_PARAMETER a;
+ TPM2B_ECC_PARAMETER b;
+ TPM2B_ECC_PARAMETER g_x;
+ TPM2B_ECC_PARAMETER g_y;
+ TPM2B_ECC_PARAMETER n;
+ TPM2B_ECC_PARAMETER h;
+};
+
+struct TPMS_SIGNATURE_RSASSA {
+ TPMI_ALG_HASH hash;
+ TPM2B_PUBLIC_KEY_RSA sig;
+};
+
+struct TPMS_SIGNATURE_RSAPSS {
+ TPMI_ALG_HASH hash;
+ TPM2B_PUBLIC_KEY_RSA sig;
+};
+
+struct TPMS_SIGNATURE_ECDSA {
+ TPMI_ALG_HASH hash;
+ TPM2B_ECC_PARAMETER signature_r;
+ TPM2B_ECC_PARAMETER signature_s;
+};
+
+union TPMU_SIGNATURE {
+ TPMS_SIGNATURE_RSASSA rsassa;
+ TPMS_SIGNATURE_RSAPSS rsapss;
+ TPMS_SIGNATURE_ECDSA ecdsa;
+ TPMS_SIGNATURE_ECDSA sm2;
+ TPMS_SIGNATURE_ECDSA ecdaa;
+ TPMS_SIGNATURE_ECDSA ecschnorr;
+ TPMT_HA hmac;
+ TPMS_SCHEME_SIGHASH any;
+};
+
+struct TPMT_SIGNATURE {
+ TPMI_ALG_SIG_SCHEME sig_alg;
+ TPMU_SIGNATURE signature;
+};
+
+union TPMU_ENCRYPTED_SECRET {
+ BYTE ecc[sizeof(TPMS_ECC_POINT)];
+ BYTE rsa[MAX_RSA_KEY_BYTES];
+ BYTE symmetric[sizeof(TPM2B_DIGEST)];
+ BYTE keyed_hash[sizeof(TPM2B_DIGEST)];
+};
+
+struct TPM2B_ENCRYPTED_SECRET {
+ UINT16 size;
+ BYTE secret[sizeof(TPMU_ENCRYPTED_SECRET)];
+};
+
+struct TPMS_KEYEDHASH_PARMS {
+ TPMT_KEYEDHASH_SCHEME scheme;
+};
+
+struct TPMS_ASYM_PARMS {
+ TPMT_SYM_DEF_OBJECT symmetric;
+ TPMT_ASYM_SCHEME scheme;
+};
+
+struct TPMS_RSA_PARMS {
+ TPMT_SYM_DEF_OBJECT symmetric;
+ TPMT_RSA_SCHEME scheme;
+ TPMI_RSA_KEY_BITS key_bits;
+ UINT32 exponent;
+};
+
+struct TPMS_ECC_PARMS {
+ TPMT_SYM_DEF_OBJECT symmetric;
+ TPMT_ECC_SCHEME scheme;
+ TPMI_ECC_CURVE curve_id;
+ TPMT_KDF_SCHEME kdf;
+};
+
+union TPMU_PUBLIC_PARMS {
+ TPMS_KEYEDHASH_PARMS keyed_hash_detail;
+ TPMS_SYMCIPHER_PARMS sym_detail;
+ TPMS_RSA_PARMS rsa_detail;
+ TPMS_ECC_PARMS ecc_detail;
+ TPMS_ASYM_PARMS asym_detail;
+};
+
+struct TPMT_PUBLIC_PARMS {
+ TPMI_ALG_PUBLIC type;
+ TPMU_PUBLIC_PARMS parameters;
+};
+
+union TPMU_PUBLIC_ID {
+ TPM2B_DIGEST keyed_hash;
+ TPM2B_DIGEST sym;
+ TPM2B_PUBLIC_KEY_RSA rsa;
+ TPMS_ECC_POINT ecc;
+};
+
+struct TPMT_PUBLIC {
+ TPMI_ALG_PUBLIC type;
+ TPMI_ALG_HASH name_alg;
+ TPMA_OBJECT object_attributes;
+ TPM2B_DIGEST auth_policy;
+ TPMU_PUBLIC_PARMS parameters;
+ TPMU_PUBLIC_ID unique;
+};
+
+struct TPM2B_PUBLIC {
+ UINT16 size;
+ TPMT_PUBLIC public_area;
+};
+
+struct TPM2B_PRIVATE_VENDOR_SPECIFIC {
+ UINT16 size;
+ BYTE buffer[PRIVATE_VENDOR_SPECIFIC_BYTES];
+};
+
+union TPMU_SENSITIVE_COMPOSITE {
+ TPM2B_PRIVATE_KEY_RSA rsa;
+ TPM2B_ECC_PARAMETER ecc;
+ TPM2B_SENSITIVE_DATA bits;
+ TPM2B_SYM_KEY sym;
+ TPM2B_PRIVATE_VENDOR_SPECIFIC any;
+};
+
+struct TPMT_SENSITIVE {
+ TPMI_ALG_PUBLIC sensitive_type;
+ TPM2B_AUTH auth_value;
+ TPM2B_DIGEST seed_value;
+ TPMU_SENSITIVE_COMPOSITE sensitive;
+};
+
+struct TPM2B_SENSITIVE {
+ UINT16 size;
+ TPMT_SENSITIVE sensitive_area;
+};
+
+struct _PRIVATE {
+ TPM2B_DIGEST integrity_outer;
+ TPM2B_DIGEST integrity_inner;
+ TPMT_SENSITIVE sensitive;
+};
+
+struct TPM2B_PRIVATE {
+ UINT16 size;
+ BYTE buffer[sizeof(_PRIVATE)];
+};
+
+struct _ID_OBJECT {
+ TPM2B_DIGEST integrity_hmac;
+ TPM2B_DIGEST enc_identity;
+};
+
+struct TPM2B_ID_OBJECT {
+ UINT16 size;
+ BYTE credential[sizeof(_ID_OBJECT)];
+};
+
+struct TPMS_NV_PUBLIC {
+ TPMI_RH_NV_INDEX nv_index;
+ TPMI_ALG_HASH name_alg;
+ TPMA_NV attributes;
+ TPM2B_DIGEST auth_policy;
+ UINT16 data_size;
+};
+
+struct TPM2B_NV_PUBLIC {
+ UINT16 size;
+ TPMS_NV_PUBLIC nv_public;
+};
+
+struct TPM2B_CONTEXT_SENSITIVE {
+ UINT16 size;
+ BYTE buffer[MAX_CONTEXT_SIZE];
+};
+
+struct TPMS_CONTEXT_DATA {
+ TPM2B_DIGEST integrity;
+ TPM2B_CONTEXT_SENSITIVE encrypted;
+};
+
+struct TPM2B_CONTEXT_DATA {
+ UINT16 size;
+ BYTE buffer[sizeof(TPMS_CONTEXT_DATA)];
+};
+
+struct TPMS_CONTEXT {
+ UINT64 sequence;
+ TPMI_DH_CONTEXT saved_handle;
+ TPMI_RH_HIERARCHY hierarchy;
+ TPM2B_CONTEXT_DATA context_blob;
+};
+
+struct TPMS_CREATION_DATA {
+ TPML_PCR_SELECTION pcr_select;
+ TPM2B_DIGEST pcr_digest;
+ TPMA_LOCALITY locality;
+ TPM_ALG_ID parent_name_alg;
+ TPM2B_NAME parent_name;
+ TPM2B_NAME parent_qualified_name;
+ TPM2B_DATA outside_info;
+};
+
+struct TPM2B_CREATION_DATA {
+ UINT16 size;
+ TPMS_CREATION_DATA creation_data;
+};
+
+
+TRUNKS_EXPORT size_t GetNumberOfRequestHandles(TPM_CC command_code);
+TRUNKS_EXPORT size_t GetNumberOfResponseHandles(TPM_CC command_code);
+
+TRUNKS_EXPORT TPM_RC Serialize_uint8_t(
+ const uint8_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_uint8_t(
+ std::string* buffer,
+ uint8_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_int8_t(
+ const int8_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_int8_t(
+ std::string* buffer,
+ int8_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_int(
+ const int& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_int(
+ std::string* buffer,
+ int* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_uint16_t(
+ const uint16_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_uint16_t(
+ std::string* buffer,
+ uint16_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_int16_t(
+ const int16_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_int16_t(
+ std::string* buffer,
+ int16_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_uint32_t(
+ const uint32_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_uint32_t(
+ std::string* buffer,
+ uint32_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_int32_t(
+ const int32_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_int32_t(
+ std::string* buffer,
+ int32_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_uint64_t(
+ const uint64_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_uint64_t(
+ std::string* buffer,
+ uint64_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_int64_t(
+ const int64_t& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_int64_t(
+ std::string* buffer,
+ int64_t* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_UINT8(
+ const UINT8& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_UINT8(
+ std::string* buffer,
+ UINT8* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_BYTE(
+ const BYTE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_BYTE(
+ std::string* buffer,
+ BYTE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_INT8(
+ const INT8& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_INT8(
+ std::string* buffer,
+ INT8* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_BOOL(
+ const BOOL& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_BOOL(
+ std::string* buffer,
+ BOOL* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_UINT16(
+ const UINT16& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_UINT16(
+ std::string* buffer,
+ UINT16* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_INT16(
+ const INT16& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_INT16(
+ std::string* buffer,
+ INT16* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_UINT32(
+ const UINT32& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_UINT32(
+ std::string* buffer,
+ UINT32* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_INT32(
+ const INT32& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_INT32(
+ std::string* buffer,
+ INT32* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_UINT64(
+ const UINT64& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_UINT64(
+ std::string* buffer,
+ UINT64* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_INT64(
+ const INT64& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_INT64(
+ std::string* buffer,
+ INT64* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_ALGORITHM_ID(
+ const TPM_ALGORITHM_ID& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_ALGORITHM_ID(
+ std::string* buffer,
+ TPM_ALGORITHM_ID* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_MODIFIER_INDICATOR(
+ const TPM_MODIFIER_INDICATOR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_MODIFIER_INDICATOR(
+ std::string* buffer,
+ TPM_MODIFIER_INDICATOR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_AUTHORIZATION_SIZE(
+ const TPM_AUTHORIZATION_SIZE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_AUTHORIZATION_SIZE(
+ std::string* buffer,
+ TPM_AUTHORIZATION_SIZE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_PARAMETER_SIZE(
+ const TPM_PARAMETER_SIZE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_PARAMETER_SIZE(
+ std::string* buffer,
+ TPM_PARAMETER_SIZE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_KEY_SIZE(
+ const TPM_KEY_SIZE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_KEY_SIZE(
+ std::string* buffer,
+ TPM_KEY_SIZE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_KEY_BITS(
+ const TPM_KEY_BITS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_KEY_BITS(
+ std::string* buffer,
+ TPM_KEY_BITS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_HANDLE(
+ const TPM_HANDLE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_HANDLE(
+ std::string* buffer,
+ TPM_HANDLE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_NONCE(
+ const TPM2B_NONCE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_NONCE(
+ std::string* buffer,
+ TPM2B_NONCE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_AUTH(
+ const TPM2B_AUTH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_AUTH(
+ std::string* buffer,
+ TPM2B_AUTH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_OPERAND(
+ const TPM2B_OPERAND& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_OPERAND(
+ std::string* buffer,
+ TPM2B_OPERAND* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_HMAC(
+ const TPMS_SCHEME_HMAC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_HMAC(
+ std::string* buffer,
+ TPMS_SCHEME_HMAC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_RSASSA(
+ const TPMS_SCHEME_RSASSA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_RSASSA(
+ std::string* buffer,
+ TPMS_SCHEME_RSASSA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_RSAPSS(
+ const TPMS_SCHEME_RSAPSS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_RSAPSS(
+ std::string* buffer,
+ TPMS_SCHEME_RSAPSS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_ECDSA(
+ const TPMS_SCHEME_ECDSA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_ECDSA(
+ std::string* buffer,
+ TPMS_SCHEME_ECDSA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_SM2(
+ const TPMS_SCHEME_SM2& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_SM2(
+ std::string* buffer,
+ TPMS_SCHEME_SM2* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_ECSCHNORR(
+ const TPMS_SCHEME_ECSCHNORR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_ECSCHNORR(
+ std::string* buffer,
+ TPMS_SCHEME_ECSCHNORR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_YES_NO(
+ const TPMI_YES_NO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_YES_NO(
+ std::string* buffer,
+ TPMI_YES_NO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_DH_OBJECT(
+ const TPMI_DH_OBJECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_DH_OBJECT(
+ std::string* buffer,
+ TPMI_DH_OBJECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_DH_PERSISTENT(
+ const TPMI_DH_PERSISTENT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_DH_PERSISTENT(
+ std::string* buffer,
+ TPMI_DH_PERSISTENT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_DH_ENTITY(
+ const TPMI_DH_ENTITY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_DH_ENTITY(
+ std::string* buffer,
+ TPMI_DH_ENTITY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_DH_PCR(
+ const TPMI_DH_PCR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_DH_PCR(
+ std::string* buffer,
+ TPMI_DH_PCR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_SH_AUTH_SESSION(
+ const TPMI_SH_AUTH_SESSION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_SH_AUTH_SESSION(
+ std::string* buffer,
+ TPMI_SH_AUTH_SESSION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_SH_HMAC(
+ const TPMI_SH_HMAC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_SH_HMAC(
+ std::string* buffer,
+ TPMI_SH_HMAC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_SH_POLICY(
+ const TPMI_SH_POLICY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_SH_POLICY(
+ std::string* buffer,
+ TPMI_SH_POLICY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_DH_CONTEXT(
+ const TPMI_DH_CONTEXT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_DH_CONTEXT(
+ std::string* buffer,
+ TPMI_DH_CONTEXT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_HIERARCHY(
+ const TPMI_RH_HIERARCHY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_HIERARCHY(
+ std::string* buffer,
+ TPMI_RH_HIERARCHY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_ENABLES(
+ const TPMI_RH_ENABLES& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_ENABLES(
+ std::string* buffer,
+ TPMI_RH_ENABLES* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_HIERARCHY_AUTH(
+ const TPMI_RH_HIERARCHY_AUTH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_HIERARCHY_AUTH(
+ std::string* buffer,
+ TPMI_RH_HIERARCHY_AUTH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_PLATFORM(
+ const TPMI_RH_PLATFORM& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_PLATFORM(
+ std::string* buffer,
+ TPMI_RH_PLATFORM* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_OWNER(
+ const TPMI_RH_OWNER& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_OWNER(
+ std::string* buffer,
+ TPMI_RH_OWNER* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_ENDORSEMENT(
+ const TPMI_RH_ENDORSEMENT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_ENDORSEMENT(
+ std::string* buffer,
+ TPMI_RH_ENDORSEMENT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_PROVISION(
+ const TPMI_RH_PROVISION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_PROVISION(
+ std::string* buffer,
+ TPMI_RH_PROVISION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_CLEAR(
+ const TPMI_RH_CLEAR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_CLEAR(
+ std::string* buffer,
+ TPMI_RH_CLEAR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_NV_AUTH(
+ const TPMI_RH_NV_AUTH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_NV_AUTH(
+ std::string* buffer,
+ TPMI_RH_NV_AUTH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_LOCKOUT(
+ const TPMI_RH_LOCKOUT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_LOCKOUT(
+ std::string* buffer,
+ TPMI_RH_LOCKOUT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RH_NV_INDEX(
+ const TPMI_RH_NV_INDEX& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RH_NV_INDEX(
+ std::string* buffer,
+ TPMI_RH_NV_INDEX* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_HASH(
+ const TPMI_ALG_HASH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_HASH(
+ std::string* buffer,
+ TPMI_ALG_HASH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_ASYM(
+ const TPMI_ALG_ASYM& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_ASYM(
+ std::string* buffer,
+ TPMI_ALG_ASYM* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_SYM(
+ const TPMI_ALG_SYM& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_SYM(
+ std::string* buffer,
+ TPMI_ALG_SYM* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_SYM_OBJECT(
+ const TPMI_ALG_SYM_OBJECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_SYM_OBJECT(
+ std::string* buffer,
+ TPMI_ALG_SYM_OBJECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_SYM_MODE(
+ const TPMI_ALG_SYM_MODE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_SYM_MODE(
+ std::string* buffer,
+ TPMI_ALG_SYM_MODE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_KDF(
+ const TPMI_ALG_KDF& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_KDF(
+ std::string* buffer,
+ TPMI_ALG_KDF* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_SIG_SCHEME(
+ const TPMI_ALG_SIG_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_SIG_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_SIG_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ECC_KEY_EXCHANGE(
+ const TPMI_ECC_KEY_EXCHANGE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ECC_KEY_EXCHANGE(
+ std::string* buffer,
+ TPMI_ECC_KEY_EXCHANGE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ST_COMMAND_TAG(
+ const TPMI_ST_COMMAND_TAG& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ST_COMMAND_TAG(
+ std::string* buffer,
+ TPMI_ST_COMMAND_TAG* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ST_ATTEST(
+ const TPMI_ST_ATTEST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ST_ATTEST(
+ std::string* buffer,
+ TPMI_ST_ATTEST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_AES_KEY_BITS(
+ const TPMI_AES_KEY_BITS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_AES_KEY_BITS(
+ std::string* buffer,
+ TPMI_AES_KEY_BITS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_SM4_KEY_BITS(
+ const TPMI_SM4_KEY_BITS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_SM4_KEY_BITS(
+ std::string* buffer,
+ TPMI_SM4_KEY_BITS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_KEYEDHASH_SCHEME(
+ const TPMI_ALG_KEYEDHASH_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_KEYEDHASH_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_KEYEDHASH_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_ASYM_SCHEME(
+ const TPMI_ALG_ASYM_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_ASYM_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_ASYM_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_RSA_SCHEME(
+ const TPMI_ALG_RSA_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_RSA_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_RSA_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_RSA_DECRYPT(
+ const TPMI_ALG_RSA_DECRYPT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_RSA_DECRYPT(
+ std::string* buffer,
+ TPMI_ALG_RSA_DECRYPT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_RSA_KEY_BITS(
+ const TPMI_RSA_KEY_BITS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_RSA_KEY_BITS(
+ std::string* buffer,
+ TPMI_RSA_KEY_BITS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_ECC_SCHEME(
+ const TPMI_ALG_ECC_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_ECC_SCHEME(
+ std::string* buffer,
+ TPMI_ALG_ECC_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ECC_CURVE(
+ const TPMI_ECC_CURVE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ECC_CURVE(
+ std::string* buffer,
+ TPMI_ECC_CURVE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMI_ALG_PUBLIC(
+ const TPMI_ALG_PUBLIC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMI_ALG_PUBLIC(
+ std::string* buffer,
+ TPMI_ALG_PUBLIC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_ALGORITHM(
+ const TPMA_ALGORITHM& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_ALGORITHM(
+ std::string* buffer,
+ TPMA_ALGORITHM* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_OBJECT(
+ const TPMA_OBJECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_OBJECT(
+ std::string* buffer,
+ TPMA_OBJECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_SESSION(
+ const TPMA_SESSION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_SESSION(
+ std::string* buffer,
+ TPMA_SESSION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_LOCALITY(
+ const TPMA_LOCALITY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_LOCALITY(
+ std::string* buffer,
+ TPMA_LOCALITY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_PERMANENT(
+ const TPMA_PERMANENT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_PERMANENT(
+ std::string* buffer,
+ TPMA_PERMANENT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_STARTUP_CLEAR(
+ const TPMA_STARTUP_CLEAR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_STARTUP_CLEAR(
+ std::string* buffer,
+ TPMA_STARTUP_CLEAR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_MEMORY(
+ const TPMA_MEMORY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_MEMORY(
+ std::string* buffer,
+ TPMA_MEMORY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_CC(
+ const TPMA_CC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_CC(
+ std::string* buffer,
+ TPMA_CC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_NV_INDEX(
+ const TPM_NV_INDEX& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_NV_INDEX(
+ std::string* buffer,
+ TPM_NV_INDEX* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMA_NV(
+ const TPMA_NV& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMA_NV(
+ std::string* buffer,
+ TPMA_NV* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_SPEC(
+ const TPM_SPEC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_SPEC(
+ std::string* buffer,
+ TPM_SPEC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_GENERATED(
+ const TPM_GENERATED& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_GENERATED(
+ std::string* buffer,
+ TPM_GENERATED* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_ALG_ID(
+ const TPM_ALG_ID& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_ALG_ID(
+ std::string* buffer,
+ TPM_ALG_ID* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_ECC_CURVE(
+ const TPM_ECC_CURVE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_ECC_CURVE(
+ std::string* buffer,
+ TPM_ECC_CURVE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_CC(
+ const TPM_CC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_CC(
+ std::string* buffer,
+ TPM_CC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_RC(
+ const TPM_RC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_RC(
+ std::string* buffer,
+ TPM_RC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_CLOCK_ADJUST(
+ const TPM_CLOCK_ADJUST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_CLOCK_ADJUST(
+ std::string* buffer,
+ TPM_CLOCK_ADJUST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_EO(
+ const TPM_EO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_EO(
+ std::string* buffer,
+ TPM_EO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_ST(
+ const TPM_ST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_ST(
+ std::string* buffer,
+ TPM_ST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_SU(
+ const TPM_SU& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_SU(
+ std::string* buffer,
+ TPM_SU* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_SE(
+ const TPM_SE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_SE(
+ std::string* buffer,
+ TPM_SE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_CAP(
+ const TPM_CAP& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_CAP(
+ std::string* buffer,
+ TPM_CAP* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_PT(
+ const TPM_PT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_PT(
+ std::string* buffer,
+ TPM_PT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_PT_PCR(
+ const TPM_PT_PCR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_PT_PCR(
+ std::string* buffer,
+ TPM_PT_PCR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_PS(
+ const TPM_PS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_PS(
+ std::string* buffer,
+ TPM_PS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_HT(
+ const TPM_HT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_HT(
+ std::string* buffer,
+ TPM_HT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_RH(
+ const TPM_RH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_RH(
+ std::string* buffer,
+ TPM_RH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM_HC(
+ const TPM_HC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM_HC(
+ std::string* buffer,
+ TPM_HC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ALGORITHM_DESCRIPTION(
+ const TPMS_ALGORITHM_DESCRIPTION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ALGORITHM_DESCRIPTION(
+ std::string* buffer,
+ TPMS_ALGORITHM_DESCRIPTION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_HA(
+ const TPMT_HA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_HA(
+ std::string* buffer,
+ TPMT_HA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_DIGEST(
+ const TPM2B_DIGEST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_DIGEST(
+ std::string* buffer,
+ TPM2B_DIGEST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_DIGEST Make_TPM2B_DIGEST(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_DIGEST(
+ const TPM2B_DIGEST& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_DATA(
+ const TPM2B_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_DATA(
+ std::string* buffer,
+ TPM2B_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_DATA Make_TPM2B_DATA(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_DATA(
+ const TPM2B_DATA& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_EVENT(
+ const TPM2B_EVENT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_EVENT(
+ std::string* buffer,
+ TPM2B_EVENT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_EVENT Make_TPM2B_EVENT(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_EVENT(
+ const TPM2B_EVENT& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_MAX_BUFFER(
+ const TPM2B_MAX_BUFFER& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_MAX_BUFFER(
+ std::string* buffer,
+ TPM2B_MAX_BUFFER* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_MAX_BUFFER Make_TPM2B_MAX_BUFFER(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_MAX_BUFFER(
+ const TPM2B_MAX_BUFFER& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_MAX_NV_BUFFER(
+ const TPM2B_MAX_NV_BUFFER& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_MAX_NV_BUFFER(
+ std::string* buffer,
+ TPM2B_MAX_NV_BUFFER* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_MAX_NV_BUFFER Make_TPM2B_MAX_NV_BUFFER(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_MAX_NV_BUFFER(
+ const TPM2B_MAX_NV_BUFFER& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_TIMEOUT(
+ const TPM2B_TIMEOUT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_TIMEOUT(
+ std::string* buffer,
+ TPM2B_TIMEOUT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_TIMEOUT Make_TPM2B_TIMEOUT(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_TIMEOUT(
+ const TPM2B_TIMEOUT& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_IV(
+ const TPM2B_IV& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_IV(
+ std::string* buffer,
+ TPM2B_IV* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_IV Make_TPM2B_IV(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_IV(
+ const TPM2B_IV& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_NAME(
+ const TPM2B_NAME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_NAME(
+ std::string* buffer,
+ TPM2B_NAME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_NAME Make_TPM2B_NAME(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_NAME(
+ const TPM2B_NAME& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_PCR_SELECT(
+ const TPMS_PCR_SELECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_PCR_SELECT(
+ std::string* buffer,
+ TPMS_PCR_SELECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_PCR_SELECTION(
+ const TPMS_PCR_SELECTION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_PCR_SELECTION(
+ std::string* buffer,
+ TPMS_PCR_SELECTION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_TK_CREATION(
+ const TPMT_TK_CREATION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_TK_CREATION(
+ std::string* buffer,
+ TPMT_TK_CREATION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_TK_VERIFIED(
+ const TPMT_TK_VERIFIED& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_TK_VERIFIED(
+ std::string* buffer,
+ TPMT_TK_VERIFIED* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_TK_AUTH(
+ const TPMT_TK_AUTH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_TK_AUTH(
+ std::string* buffer,
+ TPMT_TK_AUTH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_TK_HASHCHECK(
+ const TPMT_TK_HASHCHECK& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_TK_HASHCHECK(
+ std::string* buffer,
+ TPMT_TK_HASHCHECK* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ALG_PROPERTY(
+ const TPMS_ALG_PROPERTY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ALG_PROPERTY(
+ std::string* buffer,
+ TPMS_ALG_PROPERTY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_TAGGED_PROPERTY(
+ const TPMS_TAGGED_PROPERTY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_TAGGED_PROPERTY(
+ std::string* buffer,
+ TPMS_TAGGED_PROPERTY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_TAGGED_PCR_SELECT(
+ const TPMS_TAGGED_PCR_SELECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_TAGGED_PCR_SELECT(
+ std::string* buffer,
+ TPMS_TAGGED_PCR_SELECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_CC(
+ const TPML_CC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_CC(
+ std::string* buffer,
+ TPML_CC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_CCA(
+ const TPML_CCA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_CCA(
+ std::string* buffer,
+ TPML_CCA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_ALG(
+ const TPML_ALG& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_ALG(
+ std::string* buffer,
+ TPML_ALG* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_HANDLE(
+ const TPML_HANDLE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_HANDLE(
+ std::string* buffer,
+ TPML_HANDLE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_DIGEST(
+ const TPML_DIGEST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_DIGEST(
+ std::string* buffer,
+ TPML_DIGEST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_DIGEST_VALUES(
+ const TPML_DIGEST_VALUES& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_DIGEST_VALUES(
+ std::string* buffer,
+ TPML_DIGEST_VALUES* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_DIGEST_VALUES(
+ const TPM2B_DIGEST_VALUES& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_DIGEST_VALUES(
+ std::string* buffer,
+ TPM2B_DIGEST_VALUES* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_DIGEST_VALUES Make_TPM2B_DIGEST_VALUES(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_DIGEST_VALUES(
+ const TPM2B_DIGEST_VALUES& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_PCR_SELECTION(
+ const TPML_PCR_SELECTION& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_PCR_SELECTION(
+ std::string* buffer,
+ TPML_PCR_SELECTION* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_ALG_PROPERTY(
+ const TPML_ALG_PROPERTY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_ALG_PROPERTY(
+ std::string* buffer,
+ TPML_ALG_PROPERTY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_TAGGED_TPM_PROPERTY(
+ const TPML_TAGGED_TPM_PROPERTY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_TAGGED_TPM_PROPERTY(
+ std::string* buffer,
+ TPML_TAGGED_TPM_PROPERTY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_TAGGED_PCR_PROPERTY(
+ const TPML_TAGGED_PCR_PROPERTY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_TAGGED_PCR_PROPERTY(
+ std::string* buffer,
+ TPML_TAGGED_PCR_PROPERTY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPML_ECC_CURVE(
+ const TPML_ECC_CURVE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPML_ECC_CURVE(
+ std::string* buffer,
+ TPML_ECC_CURVE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CAPABILITY_DATA(
+ const TPMS_CAPABILITY_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CAPABILITY_DATA(
+ std::string* buffer,
+ TPMS_CAPABILITY_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CLOCK_INFO(
+ const TPMS_CLOCK_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CLOCK_INFO(
+ std::string* buffer,
+ TPMS_CLOCK_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_TIME_INFO(
+ const TPMS_TIME_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_TIME_INFO(
+ std::string* buffer,
+ TPMS_TIME_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_TIME_ATTEST_INFO(
+ const TPMS_TIME_ATTEST_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_TIME_ATTEST_INFO(
+ std::string* buffer,
+ TPMS_TIME_ATTEST_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CERTIFY_INFO(
+ const TPMS_CERTIFY_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CERTIFY_INFO(
+ std::string* buffer,
+ TPMS_CERTIFY_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_QUOTE_INFO(
+ const TPMS_QUOTE_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_QUOTE_INFO(
+ std::string* buffer,
+ TPMS_QUOTE_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_COMMAND_AUDIT_INFO(
+ const TPMS_COMMAND_AUDIT_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_COMMAND_AUDIT_INFO(
+ std::string* buffer,
+ TPMS_COMMAND_AUDIT_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SESSION_AUDIT_INFO(
+ const TPMS_SESSION_AUDIT_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SESSION_AUDIT_INFO(
+ std::string* buffer,
+ TPMS_SESSION_AUDIT_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CREATION_INFO(
+ const TPMS_CREATION_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CREATION_INFO(
+ std::string* buffer,
+ TPMS_CREATION_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_NV_CERTIFY_INFO(
+ const TPMS_NV_CERTIFY_INFO& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_NV_CERTIFY_INFO(
+ std::string* buffer,
+ TPMS_NV_CERTIFY_INFO* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ATTEST(
+ const TPMS_ATTEST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ATTEST(
+ std::string* buffer,
+ TPMS_ATTEST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_ATTEST(
+ const TPM2B_ATTEST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_ATTEST(
+ std::string* buffer,
+ TPM2B_ATTEST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_ATTEST Make_TPM2B_ATTEST(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_ATTEST(
+ const TPM2B_ATTEST& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_AUTH_COMMAND(
+ const TPMS_AUTH_COMMAND& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_AUTH_COMMAND(
+ std::string* buffer,
+ TPMS_AUTH_COMMAND* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_AUTH_RESPONSE(
+ const TPMS_AUTH_RESPONSE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_AUTH_RESPONSE(
+ std::string* buffer,
+ TPMS_AUTH_RESPONSE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_SYM_DEF(
+ const TPMT_SYM_DEF& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_SYM_DEF(
+ std::string* buffer,
+ TPMT_SYM_DEF* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_SYM_DEF_OBJECT(
+ const TPMT_SYM_DEF_OBJECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_SYM_DEF_OBJECT(
+ std::string* buffer,
+ TPMT_SYM_DEF_OBJECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_SYM_KEY(
+ const TPM2B_SYM_KEY& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_SYM_KEY(
+ std::string* buffer,
+ TPM2B_SYM_KEY* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_SYM_KEY Make_TPM2B_SYM_KEY(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_SYM_KEY(
+ const TPM2B_SYM_KEY& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SYMCIPHER_PARMS(
+ const TPMS_SYMCIPHER_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SYMCIPHER_PARMS(
+ std::string* buffer,
+ TPMS_SYMCIPHER_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_SENSITIVE_DATA(
+ const TPM2B_SENSITIVE_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_SENSITIVE_DATA(
+ std::string* buffer,
+ TPM2B_SENSITIVE_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_SENSITIVE_DATA Make_TPM2B_SENSITIVE_DATA(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_SENSITIVE_DATA(
+ const TPM2B_SENSITIVE_DATA& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SENSITIVE_CREATE(
+ const TPMS_SENSITIVE_CREATE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SENSITIVE_CREATE(
+ std::string* buffer,
+ TPMS_SENSITIVE_CREATE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_SENSITIVE_CREATE(
+ const TPM2B_SENSITIVE_CREATE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_SENSITIVE_CREATE(
+ std::string* buffer,
+ TPM2B_SENSITIVE_CREATE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_SENSITIVE_CREATE Make_TPM2B_SENSITIVE_CREATE(
+ const TPMS_SENSITIVE_CREATE& inner);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_SIGHASH(
+ const TPMS_SCHEME_SIGHASH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_SIGHASH(
+ std::string* buffer,
+ TPMS_SCHEME_SIGHASH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_XOR(
+ const TPMS_SCHEME_XOR& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_XOR(
+ std::string* buffer,
+ TPMS_SCHEME_XOR* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_KEYEDHASH_SCHEME(
+ const TPMT_KEYEDHASH_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_KEYEDHASH_SCHEME(
+ std::string* buffer,
+ TPMT_KEYEDHASH_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_ECDAA(
+ const TPMS_SCHEME_ECDAA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_ECDAA(
+ std::string* buffer,
+ TPMS_SCHEME_ECDAA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_SIG_SCHEME(
+ const TPMT_SIG_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_SIG_SCHEME(
+ std::string* buffer,
+ TPMT_SIG_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_OAEP(
+ const TPMS_SCHEME_OAEP& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_OAEP(
+ std::string* buffer,
+ TPMS_SCHEME_OAEP* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_ECDH(
+ const TPMS_SCHEME_ECDH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_ECDH(
+ std::string* buffer,
+ TPMS_SCHEME_ECDH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_MGF1(
+ const TPMS_SCHEME_MGF1& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_MGF1(
+ std::string* buffer,
+ TPMS_SCHEME_MGF1* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_KDF1_SP800_56a(
+ const TPMS_SCHEME_KDF1_SP800_56a& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_KDF1_SP800_56a(
+ std::string* buffer,
+ TPMS_SCHEME_KDF1_SP800_56a* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_KDF2(
+ const TPMS_SCHEME_KDF2& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_KDF2(
+ std::string* buffer,
+ TPMS_SCHEME_KDF2* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SCHEME_KDF1_SP800_108(
+ const TPMS_SCHEME_KDF1_SP800_108& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SCHEME_KDF1_SP800_108(
+ std::string* buffer,
+ TPMS_SCHEME_KDF1_SP800_108* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_KDF_SCHEME(
+ const TPMT_KDF_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_KDF_SCHEME(
+ std::string* buffer,
+ TPMT_KDF_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_ASYM_SCHEME(
+ const TPMT_ASYM_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_ASYM_SCHEME(
+ std::string* buffer,
+ TPMT_ASYM_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_RSA_SCHEME(
+ const TPMT_RSA_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_RSA_SCHEME(
+ std::string* buffer,
+ TPMT_RSA_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_RSA_DECRYPT(
+ const TPMT_RSA_DECRYPT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_RSA_DECRYPT(
+ std::string* buffer,
+ TPMT_RSA_DECRYPT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_PUBLIC_KEY_RSA(
+ const TPM2B_PUBLIC_KEY_RSA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_PUBLIC_KEY_RSA(
+ std::string* buffer,
+ TPM2B_PUBLIC_KEY_RSA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_PUBLIC_KEY_RSA Make_TPM2B_PUBLIC_KEY_RSA(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_PUBLIC_KEY_RSA(
+ const TPM2B_PUBLIC_KEY_RSA& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_PRIVATE_KEY_RSA(
+ const TPM2B_PRIVATE_KEY_RSA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_PRIVATE_KEY_RSA(
+ std::string* buffer,
+ TPM2B_PRIVATE_KEY_RSA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_PRIVATE_KEY_RSA Make_TPM2B_PRIVATE_KEY_RSA(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_PRIVATE_KEY_RSA(
+ const TPM2B_PRIVATE_KEY_RSA& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_ECC_PARAMETER(
+ const TPM2B_ECC_PARAMETER& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_ECC_PARAMETER(
+ std::string* buffer,
+ TPM2B_ECC_PARAMETER* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_ECC_PARAMETER Make_TPM2B_ECC_PARAMETER(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_ECC_PARAMETER(
+ const TPM2B_ECC_PARAMETER& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ECC_POINT(
+ const TPMS_ECC_POINT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ECC_POINT(
+ std::string* buffer,
+ TPMS_ECC_POINT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_ECC_POINT(
+ const TPM2B_ECC_POINT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_ECC_POINT(
+ std::string* buffer,
+ TPM2B_ECC_POINT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_ECC_POINT Make_TPM2B_ECC_POINT(
+ const TPMS_ECC_POINT& inner);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_ECC_SCHEME(
+ const TPMT_ECC_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_ECC_SCHEME(
+ std::string* buffer,
+ TPMT_ECC_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ALGORITHM_DETAIL_ECC(
+ const TPMS_ALGORITHM_DETAIL_ECC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ALGORITHM_DETAIL_ECC(
+ std::string* buffer,
+ TPMS_ALGORITHM_DETAIL_ECC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SIGNATURE_RSASSA(
+ const TPMS_SIGNATURE_RSASSA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SIGNATURE_RSASSA(
+ std::string* buffer,
+ TPMS_SIGNATURE_RSASSA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SIGNATURE_RSAPSS(
+ const TPMS_SIGNATURE_RSAPSS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SIGNATURE_RSAPSS(
+ std::string* buffer,
+ TPMS_SIGNATURE_RSAPSS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_SIGNATURE_ECDSA(
+ const TPMS_SIGNATURE_ECDSA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_SIGNATURE_ECDSA(
+ std::string* buffer,
+ TPMS_SIGNATURE_ECDSA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_SIGNATURE(
+ const TPMT_SIGNATURE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_SIGNATURE(
+ std::string* buffer,
+ TPMT_SIGNATURE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_ENCRYPTED_SECRET(
+ const TPM2B_ENCRYPTED_SECRET& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_ENCRYPTED_SECRET(
+ std::string* buffer,
+ TPM2B_ENCRYPTED_SECRET* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_ENCRYPTED_SECRET Make_TPM2B_ENCRYPTED_SECRET(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_ENCRYPTED_SECRET(
+ const TPM2B_ENCRYPTED_SECRET& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_KEYEDHASH_PARMS(
+ const TPMS_KEYEDHASH_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_KEYEDHASH_PARMS(
+ std::string* buffer,
+ TPMS_KEYEDHASH_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ASYM_PARMS(
+ const TPMS_ASYM_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ASYM_PARMS(
+ std::string* buffer,
+ TPMS_ASYM_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_RSA_PARMS(
+ const TPMS_RSA_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_RSA_PARMS(
+ std::string* buffer,
+ TPMS_RSA_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_ECC_PARMS(
+ const TPMS_ECC_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_ECC_PARMS(
+ std::string* buffer,
+ TPMS_ECC_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_PUBLIC_PARMS(
+ const TPMT_PUBLIC_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_PUBLIC_PARMS(
+ std::string* buffer,
+ TPMT_PUBLIC_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_PUBLIC(
+ const TPMT_PUBLIC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_PUBLIC(
+ std::string* buffer,
+ TPMT_PUBLIC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_PUBLIC(
+ const TPM2B_PUBLIC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_PUBLIC(
+ std::string* buffer,
+ TPM2B_PUBLIC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_PUBLIC Make_TPM2B_PUBLIC(
+ const TPMT_PUBLIC& inner);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ const TPM2B_PRIVATE_VENDOR_SPECIFIC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ std::string* buffer,
+ TPM2B_PRIVATE_VENDOR_SPECIFIC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_PRIVATE_VENDOR_SPECIFIC Make_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_PRIVATE_VENDOR_SPECIFIC(
+ const TPM2B_PRIVATE_VENDOR_SPECIFIC& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMT_SENSITIVE(
+ const TPMT_SENSITIVE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMT_SENSITIVE(
+ std::string* buffer,
+ TPMT_SENSITIVE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_SENSITIVE(
+ const TPM2B_SENSITIVE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_SENSITIVE(
+ std::string* buffer,
+ TPM2B_SENSITIVE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_SENSITIVE Make_TPM2B_SENSITIVE(
+ const TPMT_SENSITIVE& inner);
+
+TRUNKS_EXPORT TPM_RC Serialize__PRIVATE(
+ const _PRIVATE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse__PRIVATE(
+ std::string* buffer,
+ _PRIVATE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_PRIVATE(
+ const TPM2B_PRIVATE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_PRIVATE(
+ std::string* buffer,
+ TPM2B_PRIVATE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_PRIVATE Make_TPM2B_PRIVATE(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_PRIVATE(
+ const TPM2B_PRIVATE& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize__ID_OBJECT(
+ const _ID_OBJECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse__ID_OBJECT(
+ std::string* buffer,
+ _ID_OBJECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_ID_OBJECT(
+ const TPM2B_ID_OBJECT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_ID_OBJECT(
+ std::string* buffer,
+ TPM2B_ID_OBJECT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_ID_OBJECT Make_TPM2B_ID_OBJECT(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_ID_OBJECT(
+ const TPM2B_ID_OBJECT& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_NV_PUBLIC(
+ const TPMS_NV_PUBLIC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_NV_PUBLIC(
+ std::string* buffer,
+ TPMS_NV_PUBLIC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_NV_PUBLIC(
+ const TPM2B_NV_PUBLIC& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_NV_PUBLIC(
+ std::string* buffer,
+ TPM2B_NV_PUBLIC* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_NV_PUBLIC Make_TPM2B_NV_PUBLIC(
+ const TPMS_NV_PUBLIC& inner);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_CONTEXT_SENSITIVE(
+ const TPM2B_CONTEXT_SENSITIVE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_CONTEXT_SENSITIVE(
+ std::string* buffer,
+ TPM2B_CONTEXT_SENSITIVE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_CONTEXT_SENSITIVE Make_TPM2B_CONTEXT_SENSITIVE(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_CONTEXT_SENSITIVE(
+ const TPM2B_CONTEXT_SENSITIVE& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CONTEXT_DATA(
+ const TPMS_CONTEXT_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CONTEXT_DATA(
+ std::string* buffer,
+ TPMS_CONTEXT_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_CONTEXT_DATA(
+ const TPM2B_CONTEXT_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_CONTEXT_DATA(
+ std::string* buffer,
+ TPM2B_CONTEXT_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_CONTEXT_DATA Make_TPM2B_CONTEXT_DATA(
+ const std::string& bytes);
+TRUNKS_EXPORT std::string StringFrom_TPM2B_CONTEXT_DATA(
+ const TPM2B_CONTEXT_DATA& tpm2b);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CONTEXT(
+ const TPMS_CONTEXT& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CONTEXT(
+ std::string* buffer,
+ TPMS_CONTEXT* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMS_CREATION_DATA(
+ const TPMS_CREATION_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMS_CREATION_DATA(
+ std::string* buffer,
+ TPMS_CREATION_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPM2B_CREATION_DATA(
+ const TPM2B_CREATION_DATA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPM2B_CREATION_DATA(
+ std::string* buffer,
+ TPM2B_CREATION_DATA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM2B_CREATION_DATA Make_TPM2B_CREATION_DATA(
+ const TPMS_CREATION_DATA& inner);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_HA(
+ const TPMU_HA& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_HA(
+ std::string* buffer,
+ TPMU_HA* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_NAME(
+ const TPMU_NAME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_NAME(
+ std::string* buffer,
+ TPMU_NAME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_CAPABILITIES(
+ const TPMU_CAPABILITIES& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_CAPABILITIES(
+ std::string* buffer,
+ TPMU_CAPABILITIES* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_ATTEST(
+ const TPMU_ATTEST& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_ATTEST(
+ std::string* buffer,
+ TPMU_ATTEST* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SYM_KEY_BITS(
+ const TPMU_SYM_KEY_BITS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SYM_KEY_BITS(
+ std::string* buffer,
+ TPMU_SYM_KEY_BITS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SYM_MODE(
+ const TPMU_SYM_MODE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SYM_MODE(
+ std::string* buffer,
+ TPMU_SYM_MODE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SCHEME_KEYEDHASH(
+ const TPMU_SCHEME_KEYEDHASH& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SCHEME_KEYEDHASH(
+ std::string* buffer,
+ TPMU_SCHEME_KEYEDHASH* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SIG_SCHEME(
+ const TPMU_SIG_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SIG_SCHEME(
+ std::string* buffer,
+ TPMU_SIG_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_KDF_SCHEME(
+ const TPMU_KDF_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_KDF_SCHEME(
+ std::string* buffer,
+ TPMU_KDF_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_ASYM_SCHEME(
+ const TPMU_ASYM_SCHEME& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_ASYM_SCHEME(
+ std::string* buffer,
+ TPMU_ASYM_SCHEME* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SIGNATURE(
+ const TPMU_SIGNATURE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SIGNATURE(
+ std::string* buffer,
+ TPMU_SIGNATURE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_ENCRYPTED_SECRET(
+ const TPMU_ENCRYPTED_SECRET& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_ENCRYPTED_SECRET(
+ std::string* buffer,
+ TPMU_ENCRYPTED_SECRET* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_PUBLIC_ID(
+ const TPMU_PUBLIC_ID& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_PUBLIC_ID(
+ std::string* buffer,
+ TPMU_PUBLIC_ID* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_PUBLIC_PARMS(
+ const TPMU_PUBLIC_PARMS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_PUBLIC_PARMS(
+ std::string* buffer,
+ TPMU_PUBLIC_PARMS* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SENSITIVE_COMPOSITE(
+ const TPMU_SENSITIVE_COMPOSITE& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SENSITIVE_COMPOSITE(
+ std::string* buffer,
+ TPMU_SENSITIVE_COMPOSITE* value,
+ std::string* value_bytes);
+
+TRUNKS_EXPORT TPM_RC Serialize_TPMU_SYM_DETAILS(
+ const TPMU_SYM_DETAILS& value,
+ std::string* buffer);
+
+TRUNKS_EXPORT TPM_RC Parse_TPMU_SYM_DETAILS(
+ std::string* buffer,
+ TPMU_SYM_DETAILS* value,
+ std::string* value_bytes);
+
+class TRUNKS_EXPORT Tpm {
+ public:
+ // Does not take ownership of |transceiver|.
+ explicit Tpm(CommandTransceiver* transceiver) : transceiver_(transceiver) {}
+ virtual ~Tpm() {}
+
+ typedef base::Callback<void(
+ TPM_RC response_code)> StartupResponse;
+ static TPM_RC SerializeCommand_Startup(
+ const TPM_SU& startup_type,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Startup(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Startup(
+ const TPM_SU& startup_type,
+ AuthorizationDelegate* authorization_delegate,
+ const StartupResponse& callback);
+ virtual TPM_RC StartupSync(
+ const TPM_SU& startup_type,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ShutdownResponse;
+ static TPM_RC SerializeCommand_Shutdown(
+ const TPM_SU& shutdown_type,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Shutdown(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Shutdown(
+ const TPM_SU& shutdown_type,
+ AuthorizationDelegate* authorization_delegate,
+ const ShutdownResponse& callback);
+ virtual TPM_RC ShutdownSync(
+ const TPM_SU& shutdown_type,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> SelfTestResponse;
+ static TPM_RC SerializeCommand_SelfTest(
+ const TPMI_YES_NO& full_test,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_SelfTest(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void SelfTest(
+ const TPMI_YES_NO& full_test,
+ AuthorizationDelegate* authorization_delegate,
+ const SelfTestResponse& callback);
+ virtual TPM_RC SelfTestSync(
+ const TPMI_YES_NO& full_test,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPML_ALG& to_do_list)> IncrementalSelfTestResponse;
+ static TPM_RC SerializeCommand_IncrementalSelfTest(
+ const TPML_ALG& to_test,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_IncrementalSelfTest(
+ const std::string& response,
+ TPML_ALG* to_do_list,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void IncrementalSelfTest(
+ const TPML_ALG& to_test,
+ AuthorizationDelegate* authorization_delegate,
+ const IncrementalSelfTestResponse& callback);
+ virtual TPM_RC IncrementalSelfTestSync(
+ const TPML_ALG& to_test,
+ TPML_ALG* to_do_list,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_MAX_BUFFER& out_data,
+ const TPM_RC& test_result)> GetTestResultResponse;
+ static TPM_RC SerializeCommand_GetTestResult(
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_GetTestResult(
+ const std::string& response,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM_RC* test_result,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void GetTestResult(
+ AuthorizationDelegate* authorization_delegate,
+ const GetTestResultResponse& callback);
+ virtual TPM_RC GetTestResultSync(
+ TPM2B_MAX_BUFFER* out_data,
+ TPM_RC* test_result,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMI_SH_AUTH_SESSION& session_handle,
+ const TPM2B_NONCE& nonce_tpm)> StartAuthSessionResponse;
+ static TPM_RC SerializeCommand_StartAuthSession(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_StartAuthSession(
+ const std::string& response,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void StartAuthSession(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const StartAuthSessionResponse& callback);
+ virtual TPM_RC StartAuthSessionSync(
+ const TPMI_DH_OBJECT& tpm_key,
+ const std::string& tpm_key_name,
+ const TPMI_DH_ENTITY& bind,
+ const std::string& bind_name,
+ const TPM2B_NONCE& nonce_caller,
+ const TPM2B_ENCRYPTED_SECRET& encrypted_salt,
+ const TPM_SE& session_type,
+ const TPMT_SYM_DEF& symmetric,
+ const TPMI_ALG_HASH& auth_hash,
+ TPMI_SH_AUTH_SESSION* session_handle,
+ TPM2B_NONCE* nonce_tpm,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyRestartResponse;
+ static TPM_RC SerializeCommand_PolicyRestart(
+ const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyRestart(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyRestart(
+ const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyRestartResponse& callback);
+ virtual TPM_RC PolicyRestartSync(
+ const TPMI_SH_POLICY& session_handle,
+ const std::string& session_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PRIVATE& out_private,
+ const TPM2B_PUBLIC& out_public,
+ const TPM2B_CREATION_DATA& creation_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_TK_CREATION& creation_ticket)> CreateResponse;
+ static TPM_RC SerializeCommand_Create(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Create(
+ const std::string& response,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Create(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ AuthorizationDelegate* authorization_delegate,
+ const CreateResponse& callback);
+ virtual TPM_RC CreateSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM2B_PRIVATE* out_private,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM_HANDLE& object_handle,
+ const TPM2B_NAME& name)> LoadResponse;
+ static TPM_RC SerializeCommand_Load(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Load(
+ const std::string& response,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Load(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ AuthorizationDelegate* authorization_delegate,
+ const LoadResponse& callback);
+ virtual TPM_RC LoadSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_PRIVATE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM_HANDLE& object_handle,
+ const TPM2B_NAME& name)> LoadExternalResponse;
+ static TPM_RC SerializeCommand_LoadExternal(
+ const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_LoadExternal(
+ const std::string& response,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void LoadExternal(
+ const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const LoadExternalResponse& callback);
+ virtual TPM_RC LoadExternalSync(
+ const TPM2B_SENSITIVE& in_private,
+ const TPM2B_PUBLIC& in_public,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM_HANDLE* object_handle,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PUBLIC& out_public,
+ const TPM2B_NAME& name,
+ const TPM2B_NAME& qualified_name)> ReadPublicResponse;
+ static TPM_RC SerializeCommand_ReadPublic(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ReadPublic(
+ const std::string& response,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_NAME* name,
+ TPM2B_NAME* qualified_name,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ReadPublic(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ReadPublicResponse& callback);
+ virtual TPM_RC ReadPublicSync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_NAME* name,
+ TPM2B_NAME* qualified_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DIGEST& cert_info)> ActivateCredentialResponse;
+ static TPM_RC SerializeCommand_ActivateCredential(
+ const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ActivateCredential(
+ const std::string& response,
+ TPM2B_DIGEST* cert_info,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ActivateCredential(
+ const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ AuthorizationDelegate* authorization_delegate,
+ const ActivateCredentialResponse& callback);
+ virtual TPM_RC ActivateCredentialSync(
+ const TPMI_DH_OBJECT& activate_handle,
+ const std::string& activate_handle_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret,
+ TPM2B_DIGEST* cert_info,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ID_OBJECT& credential_blob,
+ const TPM2B_ENCRYPTED_SECRET& secret)> MakeCredentialResponse;
+ static TPM_RC SerializeCommand_MakeCredential(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_MakeCredential(
+ const std::string& response,
+ TPM2B_ID_OBJECT* credential_blob,
+ TPM2B_ENCRYPTED_SECRET* secret,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void MakeCredential(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ AuthorizationDelegate* authorization_delegate,
+ const MakeCredentialResponse& callback);
+ virtual TPM_RC MakeCredentialSync(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_DIGEST& credential,
+ const TPM2B_NAME& object_name,
+ TPM2B_ID_OBJECT* credential_blob,
+ TPM2B_ENCRYPTED_SECRET* secret,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_SENSITIVE_DATA& out_data)> UnsealResponse;
+ static TPM_RC SerializeCommand_Unseal(
+ const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Unseal(
+ const std::string& response,
+ TPM2B_SENSITIVE_DATA* out_data,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Unseal(
+ const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const UnsealResponse& callback);
+ virtual TPM_RC UnsealSync(
+ const TPMI_DH_OBJECT& item_handle,
+ const std::string& item_handle_name,
+ TPM2B_SENSITIVE_DATA* out_data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PRIVATE& out_private)> ObjectChangeAuthResponse;
+ static TPM_RC SerializeCommand_ObjectChangeAuth(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ObjectChangeAuth(
+ const std::string& response,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ObjectChangeAuth(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const ObjectChangeAuthResponse& callback);
+ virtual TPM_RC ObjectChangeAuthSync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_AUTH& new_auth,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DATA& encryption_key_out,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& out_sym_seed)> DuplicateResponse;
+ static TPM_RC SerializeCommand_Duplicate(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Duplicate(
+ const std::string& response,
+ TPM2B_DATA* encryption_key_out,
+ TPM2B_PRIVATE* duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Duplicate(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const DuplicateResponse& callback);
+ virtual TPM_RC DuplicateSync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& new_parent_handle,
+ const std::string& new_parent_handle_name,
+ const TPM2B_DATA& encryption_key_in,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ TPM2B_DATA* encryption_key_out,
+ TPM2B_PRIVATE* duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PRIVATE& out_duplicate,
+ const TPM2B_ENCRYPTED_SECRET& out_sym_seed)> RewrapResponse;
+ static TPM_RC SerializeCommand_Rewrap(
+ const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Rewrap(
+ const std::string& response,
+ TPM2B_PRIVATE* out_duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Rewrap(
+ const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ AuthorizationDelegate* authorization_delegate,
+ const RewrapResponse& callback);
+ virtual TPM_RC RewrapSync(
+ const TPMI_DH_OBJECT& old_parent,
+ const std::string& old_parent_name,
+ const TPMI_DH_OBJECT& new_parent,
+ const std::string& new_parent_name,
+ const TPM2B_PRIVATE& in_duplicate,
+ const TPM2B_NAME& name,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ TPM2B_PRIVATE* out_duplicate,
+ TPM2B_ENCRYPTED_SECRET* out_sym_seed,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PRIVATE& out_private)> ImportResponse;
+ static TPM_RC SerializeCommand_Import(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Import(
+ const std::string& response,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Import(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const ImportResponse& callback);
+ virtual TPM_RC ImportSync(
+ const TPMI_DH_OBJECT& parent_handle,
+ const std::string& parent_handle_name,
+ const TPM2B_DATA& encryption_key,
+ const TPM2B_PUBLIC& object_public,
+ const TPM2B_PRIVATE& duplicate,
+ const TPM2B_ENCRYPTED_SECRET& in_sym_seed,
+ const TPMT_SYM_DEF_OBJECT& symmetric_alg,
+ TPM2B_PRIVATE* out_private,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PUBLIC_KEY_RSA& out_data)> RSA_EncryptResponse;
+ static TPM_RC SerializeCommand_RSA_Encrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_RSA_Encrypt(
+ const std::string& response,
+ TPM2B_PUBLIC_KEY_RSA* out_data,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void RSA_Encrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ AuthorizationDelegate* authorization_delegate,
+ const RSA_EncryptResponse& callback);
+ virtual TPM_RC RSA_EncryptSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& message,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ TPM2B_PUBLIC_KEY_RSA* out_data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_PUBLIC_KEY_RSA& message)> RSA_DecryptResponse;
+ static TPM_RC SerializeCommand_RSA_Decrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_RSA_Decrypt(
+ const std::string& response,
+ TPM2B_PUBLIC_KEY_RSA* message,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void RSA_Decrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ AuthorizationDelegate* authorization_delegate,
+ const RSA_DecryptResponse& callback);
+ virtual TPM_RC RSA_DecryptSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_PUBLIC_KEY_RSA& cipher_text,
+ const TPMT_RSA_DECRYPT& in_scheme,
+ const TPM2B_DATA& label,
+ TPM2B_PUBLIC_KEY_RSA* message,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ECC_POINT& z_point,
+ const TPM2B_ECC_POINT& pub_point)> ECDH_KeyGenResponse;
+ static TPM_RC SerializeCommand_ECDH_KeyGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ECDH_KeyGen(
+ const std::string& response,
+ TPM2B_ECC_POINT* z_point,
+ TPM2B_ECC_POINT* pub_point,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ECDH_KeyGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ECDH_KeyGenResponse& callback);
+ virtual TPM_RC ECDH_KeyGenSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ TPM2B_ECC_POINT* z_point,
+ TPM2B_ECC_POINT* pub_point,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ECC_POINT& out_point)> ECDH_ZGenResponse;
+ static TPM_RC SerializeCommand_ECDH_ZGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ECDH_ZGen(
+ const std::string& response,
+ TPM2B_ECC_POINT* out_point,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ECDH_ZGen(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ AuthorizationDelegate* authorization_delegate,
+ const ECDH_ZGenResponse& callback);
+ virtual TPM_RC ECDH_ZGenSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_ECC_POINT& in_point,
+ TPM2B_ECC_POINT* out_point,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMS_ALGORITHM_DETAIL_ECC& parameters)> ECC_ParametersResponse;
+ static TPM_RC SerializeCommand_ECC_Parameters(
+ const TPMI_ECC_CURVE& curve_id,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ECC_Parameters(
+ const std::string& response,
+ TPMS_ALGORITHM_DETAIL_ECC* parameters,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ECC_Parameters(
+ const TPMI_ECC_CURVE& curve_id,
+ AuthorizationDelegate* authorization_delegate,
+ const ECC_ParametersResponse& callback);
+ virtual TPM_RC ECC_ParametersSync(
+ const TPMI_ECC_CURVE& curve_id,
+ TPMS_ALGORITHM_DETAIL_ECC* parameters,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ECC_POINT& out_z1,
+ const TPM2B_ECC_POINT& out_z2)> ZGen_2PhaseResponse;
+ static TPM_RC SerializeCommand_ZGen_2Phase(
+ const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ZGen_2Phase(
+ const std::string& response,
+ TPM2B_ECC_POINT* out_z1,
+ TPM2B_ECC_POINT* out_z2,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ZGen_2Phase(
+ const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ AuthorizationDelegate* authorization_delegate,
+ const ZGen_2PhaseResponse& callback);
+ virtual TPM_RC ZGen_2PhaseSync(
+ const TPMI_DH_OBJECT& key_a,
+ const std::string& key_a_name,
+ const TPM2B_ECC_POINT& in_qs_b,
+ const TPM2B_ECC_POINT& in_qe_b,
+ const TPMI_ECC_KEY_EXCHANGE& in_scheme,
+ const UINT16& counter,
+ TPM2B_ECC_POINT* out_z1,
+ TPM2B_ECC_POINT* out_z2,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_MAX_BUFFER& out_data,
+ const TPM2B_IV& iv_out)> EncryptDecryptResponse;
+ static TPM_RC SerializeCommand_EncryptDecrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_EncryptDecrypt(
+ const std::string& response,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM2B_IV* iv_out,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void EncryptDecrypt(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ AuthorizationDelegate* authorization_delegate,
+ const EncryptDecryptResponse& callback);
+ virtual TPM_RC EncryptDecryptSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPMI_YES_NO& decrypt,
+ const TPMI_ALG_SYM_MODE& mode,
+ const TPM2B_IV& iv_in,
+ const TPM2B_MAX_BUFFER& in_data,
+ TPM2B_MAX_BUFFER* out_data,
+ TPM2B_IV* iv_out,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DIGEST& out_hash,
+ const TPMT_TK_HASHCHECK& validation)> HashResponse;
+ static TPM_RC SerializeCommand_Hash(
+ const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Hash(
+ const std::string& response,
+ TPM2B_DIGEST* out_hash,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Hash(
+ const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const HashResponse& callback);
+ virtual TPM_RC HashSync(
+ const TPM2B_MAX_BUFFER& data,
+ const TPMI_ALG_HASH& hash_alg,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM2B_DIGEST* out_hash,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DIGEST& out_hmac)> HMACResponse;
+ static TPM_RC SerializeCommand_HMAC(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_HMAC(
+ const std::string& response,
+ TPM2B_DIGEST* out_hmac,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void HMAC(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HMACResponse& callback);
+ virtual TPM_RC HMACSync(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_ALG_HASH& hash_alg,
+ TPM2B_DIGEST* out_hmac,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DIGEST& random_bytes)> GetRandomResponse;
+ static TPM_RC SerializeCommand_GetRandom(
+ const UINT16& bytes_requested,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_GetRandom(
+ const std::string& response,
+ TPM2B_DIGEST* random_bytes,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void GetRandom(
+ const UINT16& bytes_requested,
+ AuthorizationDelegate* authorization_delegate,
+ const GetRandomResponse& callback);
+ virtual TPM_RC GetRandomSync(
+ const UINT16& bytes_requested,
+ TPM2B_DIGEST* random_bytes,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> StirRandomResponse;
+ static TPM_RC SerializeCommand_StirRandom(
+ const TPM2B_SENSITIVE_DATA& in_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_StirRandom(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void StirRandom(
+ const TPM2B_SENSITIVE_DATA& in_data,
+ AuthorizationDelegate* authorization_delegate,
+ const StirRandomResponse& callback);
+ virtual TPM_RC StirRandomSync(
+ const TPM2B_SENSITIVE_DATA& in_data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMI_DH_OBJECT& sequence_handle)> HMAC_StartResponse;
+ static TPM_RC SerializeCommand_HMAC_Start(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_HMAC_Start(
+ const std::string& response,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void HMAC_Start(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HMAC_StartResponse& callback);
+ virtual TPM_RC HMAC_StartSync(
+ const TPMI_DH_OBJECT& handle,
+ const std::string& handle_name,
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMI_DH_OBJECT& sequence_handle)> HashSequenceStartResponse;
+ static TPM_RC SerializeCommand_HashSequenceStart(
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_HashSequenceStart(
+ const std::string& response,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void HashSequenceStart(
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const HashSequenceStartResponse& callback);
+ virtual TPM_RC HashSequenceStartSync(
+ const TPM2B_AUTH& auth,
+ const TPMI_ALG_HASH& hash_alg,
+ TPMI_DH_OBJECT* sequence_handle,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> SequenceUpdateResponse;
+ static TPM_RC SerializeCommand_SequenceUpdate(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_SequenceUpdate(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void SequenceUpdate(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate,
+ const SequenceUpdateResponse& callback);
+ virtual TPM_RC SequenceUpdateSync(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DIGEST& result,
+ const TPMT_TK_HASHCHECK& validation)> SequenceCompleteResponse;
+ static TPM_RC SerializeCommand_SequenceComplete(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_SequenceComplete(
+ const std::string& response,
+ TPM2B_DIGEST* result,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void SequenceComplete(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ AuthorizationDelegate* authorization_delegate,
+ const SequenceCompleteResponse& callback);
+ virtual TPM_RC SequenceCompleteSync(
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ const TPMI_RH_HIERARCHY& hierarchy,
+ TPM2B_DIGEST* result,
+ TPMT_TK_HASHCHECK* validation,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPML_DIGEST_VALUES& results)> EventSequenceCompleteResponse;
+ static TPM_RC SerializeCommand_EventSequenceComplete(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_EventSequenceComplete(
+ const std::string& response,
+ TPML_DIGEST_VALUES* results,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void EventSequenceComplete(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ AuthorizationDelegate* authorization_delegate,
+ const EventSequenceCompleteResponse& callback);
+ virtual TPM_RC EventSequenceCompleteSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPMI_DH_OBJECT& sequence_handle,
+ const std::string& sequence_handle_name,
+ const TPM2B_MAX_BUFFER& buffer,
+ TPML_DIGEST_VALUES* results,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& certify_info,
+ const TPMT_SIGNATURE& signature)> CertifyResponse;
+ static TPM_RC SerializeCommand_Certify(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Certify(
+ const std::string& response,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Certify(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const CertifyResponse& callback);
+ virtual TPM_RC CertifySync(
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& certify_info,
+ const TPMT_SIGNATURE& signature)> CertifyCreationResponse;
+ static TPM_RC SerializeCommand_CertifyCreation(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_CertifyCreation(
+ const std::string& response,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void CertifyCreation(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const CertifyCreationResponse& callback);
+ virtual TPM_RC CertifyCreationSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_CREATION& creation_ticket,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& quoted,
+ const TPMT_SIGNATURE& signature)> QuoteResponse;
+ static TPM_RC SerializeCommand_Quote(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Quote(
+ const std::string& response,
+ TPM2B_ATTEST* quoted,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Quote(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ AuthorizationDelegate* authorization_delegate,
+ const QuoteResponse& callback);
+ virtual TPM_RC QuoteSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPML_PCR_SELECTION& pcrselect,
+ TPM2B_ATTEST* quoted,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& audit_info,
+ const TPMT_SIGNATURE& signature)> GetSessionAuditDigestResponse;
+ static TPM_RC SerializeCommand_GetSessionAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_GetSessionAuditDigest(
+ const std::string& response,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void GetSessionAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetSessionAuditDigestResponse& callback);
+ virtual TPM_RC GetSessionAuditDigestSync(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_SH_HMAC& session_handle,
+ const std::string& session_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& audit_info,
+ const TPMT_SIGNATURE& signature)> GetCommandAuditDigestResponse;
+ static TPM_RC SerializeCommand_GetCommandAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_GetCommandAuditDigest(
+ const std::string& response,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void GetCommandAuditDigest(
+ const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetCommandAuditDigestResponse& callback);
+ virtual TPM_RC GetCommandAuditDigestSync(
+ const TPMI_RH_ENDORSEMENT& privacy_handle,
+ const std::string& privacy_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* audit_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& time_info,
+ const TPMT_SIGNATURE& signature)> GetTimeResponse;
+ static TPM_RC SerializeCommand_GetTime(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_GetTime(
+ const std::string& response,
+ TPM2B_ATTEST* time_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void GetTime(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ AuthorizationDelegate* authorization_delegate,
+ const GetTimeResponse& callback);
+ virtual TPM_RC GetTimeSync(
+ const TPMI_RH_ENDORSEMENT& privacy_admin_handle,
+ const std::string& privacy_admin_handle_name,
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ TPM2B_ATTEST* time_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const UINT32& param_size_out,
+ const TPM2B_ECC_POINT& k,
+ const TPM2B_ECC_POINT& l,
+ const TPM2B_ECC_POINT& e,
+ const UINT16& counter)> CommitResponse;
+ static TPM_RC SerializeCommand_Commit(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Commit(
+ const std::string& response,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Commit(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ AuthorizationDelegate* authorization_delegate,
+ const CommitResponse& callback);
+ virtual TPM_RC CommitSync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const UINT32& param_size,
+ const TPM2B_ECC_POINT& p1,
+ const TPM2B_SENSITIVE_DATA& s2,
+ const TPM2B_ECC_PARAMETER& y2,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* k,
+ TPM2B_ECC_POINT* l,
+ TPM2B_ECC_POINT* e,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const UINT32& param_size_out,
+ const TPM2B_ECC_POINT& q,
+ const UINT16& counter)> EC_EphemeralResponse;
+ static TPM_RC SerializeCommand_EC_Ephemeral(
+ const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_EC_Ephemeral(
+ const std::string& response,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* q,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void EC_Ephemeral(
+ const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ AuthorizationDelegate* authorization_delegate,
+ const EC_EphemeralResponse& callback);
+ virtual TPM_RC EC_EphemeralSync(
+ const UINT32& param_size,
+ const TPMI_ECC_CURVE& curve_id,
+ UINT32* param_size_out,
+ TPM2B_ECC_POINT* q,
+ UINT16* counter,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMT_TK_VERIFIED& validation)> VerifySignatureResponse;
+ static TPM_RC SerializeCommand_VerifySignature(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_VerifySignature(
+ const std::string& response,
+ TPMT_TK_VERIFIED* validation,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void VerifySignature(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ AuthorizationDelegate* authorization_delegate,
+ const VerifySignatureResponse& callback);
+ virtual TPM_RC VerifySignatureSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIGNATURE& signature,
+ TPMT_TK_VERIFIED* validation,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMT_SIGNATURE& signature)> SignResponse;
+ static TPM_RC SerializeCommand_Sign(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Sign(
+ const std::string& response,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Sign(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ AuthorizationDelegate* authorization_delegate,
+ const SignResponse& callback);
+ virtual TPM_RC SignSync(
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& digest,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const TPMT_TK_HASHCHECK& validation,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> SetCommandCodeAuditStatusResponse;
+ static TPM_RC SerializeCommand_SetCommandCodeAuditStatus(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_SetCommandCodeAuditStatus(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void SetCommandCodeAuditStatus(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate,
+ const SetCommandCodeAuditStatusResponse& callback);
+ virtual TPM_RC SetCommandCodeAuditStatusSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_ALG_HASH& audit_alg,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PCR_ExtendResponse;
+ static TPM_RC SerializeCommand_PCR_Extend(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_Extend(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_Extend(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ExtendResponse& callback);
+ virtual TPM_RC PCR_ExtendSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPML_DIGEST_VALUES& digests,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPML_DIGEST_VALUES& digests)> PCR_EventResponse;
+ static TPM_RC SerializeCommand_PCR_Event(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_Event(
+ const std::string& response,
+ TPML_DIGEST_VALUES* digests,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_Event(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_EventResponse& callback);
+ virtual TPM_RC PCR_EventSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_EVENT& event_data,
+ TPML_DIGEST_VALUES* digests,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const UINT32& pcr_update_counter,
+ const TPML_PCR_SELECTION& pcr_selection_out,
+ const TPML_DIGEST& pcr_values)> PCR_ReadResponse;
+ static TPM_RC SerializeCommand_PCR_Read(
+ const TPML_PCR_SELECTION& pcr_selection_in,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_Read(
+ const std::string& response,
+ UINT32* pcr_update_counter,
+ TPML_PCR_SELECTION* pcr_selection_out,
+ TPML_DIGEST* pcr_values,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_Read(
+ const TPML_PCR_SELECTION& pcr_selection_in,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ReadResponse& callback);
+ virtual TPM_RC PCR_ReadSync(
+ const TPML_PCR_SELECTION& pcr_selection_in,
+ UINT32* pcr_update_counter,
+ TPML_PCR_SELECTION* pcr_selection_out,
+ TPML_DIGEST* pcr_values,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMI_YES_NO& allocation_success,
+ const UINT32& max_pcr,
+ const UINT32& size_needed,
+ const UINT32& size_available)> PCR_AllocateResponse;
+ static TPM_RC SerializeCommand_PCR_Allocate(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_Allocate(
+ const std::string& response,
+ TPMI_YES_NO* allocation_success,
+ UINT32* max_pcr,
+ UINT32* size_needed,
+ UINT32* size_available,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_Allocate(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_AllocateResponse& callback);
+ virtual TPM_RC PCR_AllocateSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPML_PCR_SELECTION& pcr_allocation,
+ TPMI_YES_NO* allocation_success,
+ UINT32* max_pcr,
+ UINT32* size_needed,
+ UINT32* size_available,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PCR_SetAuthPolicyResponse;
+ static TPM_RC SerializeCommand_PCR_SetAuthPolicy(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_SetAuthPolicy(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_SetAuthPolicy(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_SetAuthPolicyResponse& callback);
+ virtual TPM_RC PCR_SetAuthPolicySync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_DH_PCR& pcr_num,
+ const std::string& pcr_num_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& policy_digest,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PCR_SetAuthValueResponse;
+ static TPM_RC SerializeCommand_PCR_SetAuthValue(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_SetAuthValue(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_SetAuthValue(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_SetAuthValueResponse& callback);
+ virtual TPM_RC PCR_SetAuthValueSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ const TPM2B_DIGEST& auth,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PCR_ResetResponse;
+ static TPM_RC SerializeCommand_PCR_Reset(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PCR_Reset(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PCR_Reset(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PCR_ResetResponse& callback);
+ virtual TPM_RC PCR_ResetSync(
+ const TPMI_DH_PCR& pcr_handle,
+ const std::string& pcr_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_TIMEOUT& timeout,
+ const TPMT_TK_AUTH& policy_ticket)> PolicySignedResponse;
+ static TPM_RC SerializeCommand_PolicySigned(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicySigned(
+ const std::string& response,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicySigned(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySignedResponse& callback);
+ virtual TPM_RC PolicySignedSync(
+ const TPMI_DH_OBJECT& auth_object,
+ const std::string& auth_object_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ const TPMT_SIGNATURE& auth,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_TIMEOUT& timeout,
+ const TPMT_TK_AUTH& policy_ticket)> PolicySecretResponse;
+ static TPM_RC SerializeCommand_PolicySecret(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicySecret(
+ const std::string& response,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicySecret(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicySecretResponse& callback);
+ virtual TPM_RC PolicySecretSync(
+ const TPMI_DH_ENTITY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NONCE& nonce_tpm,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const INT32& expiration,
+ TPM2B_TIMEOUT* timeout,
+ TPMT_TK_AUTH* policy_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyTicketResponse;
+ static TPM_RC SerializeCommand_PolicyTicket(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyTicket(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyTicket(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyTicketResponse& callback);
+ virtual TPM_RC PolicyTicketSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_TIMEOUT& timeout,
+ const TPM2B_DIGEST& cp_hash_a,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& auth_name,
+ const TPMT_TK_AUTH& ticket,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyORResponse;
+ static TPM_RC SerializeCommand_PolicyOR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyOR(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyOR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyORResponse& callback);
+ virtual TPM_RC PolicyORSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPML_DIGEST& p_hash_list,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyPCRResponse;
+ static TPM_RC SerializeCommand_PolicyPCR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyPCR(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyPCR(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPCRResponse& callback);
+ virtual TPM_RC PolicyPCRSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& pcr_digest,
+ const TPML_PCR_SELECTION& pcrs,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyLocalityResponse;
+ static TPM_RC SerializeCommand_PolicyLocality(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyLocality(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyLocality(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyLocalityResponse& callback);
+ virtual TPM_RC PolicyLocalitySync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMA_LOCALITY& locality,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyNVResponse;
+ static TPM_RC SerializeCommand_PolicyNV(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyNV(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyNV(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNVResponse& callback);
+ virtual TPM_RC PolicyNVSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyCounterTimerResponse;
+ static TPM_RC SerializeCommand_PolicyCounterTimer(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyCounterTimer(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyCounterTimer(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCounterTimerResponse& callback);
+ virtual TPM_RC PolicyCounterTimerSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_OPERAND& operand_b,
+ const UINT16& offset,
+ const TPM_EO& operation,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyCommandCodeResponse;
+ static TPM_RC SerializeCommand_PolicyCommandCode(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyCommandCode(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyCommandCode(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCommandCodeResponse& callback);
+ virtual TPM_RC PolicyCommandCodeSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM_CC& code,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyPhysicalPresenceResponse;
+ static TPM_RC SerializeCommand_PolicyPhysicalPresence(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyPhysicalPresence(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyPhysicalPresence(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPhysicalPresenceResponse& callback);
+ virtual TPM_RC PolicyPhysicalPresenceSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyCpHashResponse;
+ static TPM_RC SerializeCommand_PolicyCpHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyCpHash(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyCpHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyCpHashResponse& callback);
+ virtual TPM_RC PolicyCpHashSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& cp_hash_a,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyNameHashResponse;
+ static TPM_RC SerializeCommand_PolicyNameHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyNameHash(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyNameHash(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNameHashResponse& callback);
+ virtual TPM_RC PolicyNameHashSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& name_hash,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyDuplicationSelectResponse;
+ static TPM_RC SerializeCommand_PolicyDuplicationSelect(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyDuplicationSelect(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyDuplicationSelect(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyDuplicationSelectResponse& callback);
+ virtual TPM_RC PolicyDuplicationSelectSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_NAME& object_name,
+ const TPM2B_NAME& new_parent_name,
+ const TPMI_YES_NO& include_object,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyAuthorizeResponse;
+ static TPM_RC SerializeCommand_PolicyAuthorize(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyAuthorize(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyAuthorize(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyAuthorizeResponse& callback);
+ virtual TPM_RC PolicyAuthorizeSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPM2B_DIGEST& approved_policy,
+ const TPM2B_NONCE& policy_ref,
+ const TPM2B_NAME& key_sign,
+ const TPMT_TK_VERIFIED& check_ticket,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyAuthValueResponse;
+ static TPM_RC SerializeCommand_PolicyAuthValue(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyAuthValue(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyAuthValue(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyAuthValueResponse& callback);
+ virtual TPM_RC PolicyAuthValueSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyPasswordResponse;
+ static TPM_RC SerializeCommand_PolicyPassword(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyPassword(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyPassword(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyPasswordResponse& callback);
+ virtual TPM_RC PolicyPasswordSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_DIGEST& policy_digest)> PolicyGetDigestResponse;
+ static TPM_RC SerializeCommand_PolicyGetDigest(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyGetDigest(
+ const std::string& response,
+ TPM2B_DIGEST* policy_digest,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyGetDigest(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyGetDigestResponse& callback);
+ virtual TPM_RC PolicyGetDigestSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ TPM2B_DIGEST* policy_digest,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PolicyNvWrittenResponse;
+ static TPM_RC SerializeCommand_PolicyNvWritten(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PolicyNvWritten(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PolicyNvWritten(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ AuthorizationDelegate* authorization_delegate,
+ const PolicyNvWrittenResponse& callback);
+ virtual TPM_RC PolicyNvWrittenSync(
+ const TPMI_SH_POLICY& policy_session,
+ const std::string& policy_session_name,
+ const TPMI_YES_NO& written_set,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM_HANDLE& object_handle,
+ const TPM2B_PUBLIC& out_public,
+ const TPM2B_CREATION_DATA& creation_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_TK_CREATION& creation_ticket,
+ const TPM2B_NAME& name)> CreatePrimaryResponse;
+ static TPM_RC SerializeCommand_CreatePrimary(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_CreatePrimary(
+ const std::string& response,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void CreatePrimary(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ AuthorizationDelegate* authorization_delegate,
+ const CreatePrimaryResponse& callback);
+ virtual TPM_RC CreatePrimarySync(
+ const TPMI_RH_HIERARCHY& primary_handle,
+ const std::string& primary_handle_name,
+ const TPM2B_SENSITIVE_CREATE& in_sensitive,
+ const TPM2B_PUBLIC& in_public,
+ const TPM2B_DATA& outside_info,
+ const TPML_PCR_SELECTION& creation_pcr,
+ TPM_HANDLE* object_handle,
+ TPM2B_PUBLIC* out_public,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket,
+ TPM2B_NAME* name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> HierarchyControlResponse;
+ static TPM_RC SerializeCommand_HierarchyControl(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_HierarchyControl(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void HierarchyControl(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ AuthorizationDelegate* authorization_delegate,
+ const HierarchyControlResponse& callback);
+ virtual TPM_RC HierarchyControlSync(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_ENABLES& enable,
+ const TPMI_YES_NO& state,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> SetPrimaryPolicyResponse;
+ static TPM_RC SerializeCommand_SetPrimaryPolicy(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_SetPrimaryPolicy(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void SetPrimaryPolicy(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate,
+ const SetPrimaryPolicyResponse& callback);
+ virtual TPM_RC SetPrimaryPolicySync(
+ const TPMI_RH_HIERARCHY& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_DIGEST& auth_policy,
+ const TPMI_ALG_HASH& hash_alg,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ChangePPSResponse;
+ static TPM_RC SerializeCommand_ChangePPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ChangePPS(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ChangePPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ChangePPSResponse& callback);
+ virtual TPM_RC ChangePPSSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ChangeEPSResponse;
+ static TPM_RC SerializeCommand_ChangeEPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ChangeEPS(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ChangeEPS(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ChangeEPSResponse& callback);
+ virtual TPM_RC ChangeEPSSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ClearResponse;
+ static TPM_RC SerializeCommand_Clear(
+ const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_Clear(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void Clear(
+ const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ClearResponse& callback);
+ virtual TPM_RC ClearSync(
+ const TPMI_RH_CLEAR& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ClearControlResponse;
+ static TPM_RC SerializeCommand_ClearControl(
+ const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ClearControl(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ClearControl(
+ const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ AuthorizationDelegate* authorization_delegate,
+ const ClearControlResponse& callback);
+ virtual TPM_RC ClearControlSync(
+ const TPMI_RH_CLEAR& auth,
+ const std::string& auth_name,
+ const TPMI_YES_NO& disable,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> HierarchyChangeAuthResponse;
+ static TPM_RC SerializeCommand_HierarchyChangeAuth(
+ const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_HierarchyChangeAuth(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void HierarchyChangeAuth(
+ const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const HierarchyChangeAuthResponse& callback);
+ virtual TPM_RC HierarchyChangeAuthSync(
+ const TPMI_RH_HIERARCHY_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> DictionaryAttackLockResetResponse;
+ static TPM_RC SerializeCommand_DictionaryAttackLockReset(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_DictionaryAttackLockReset(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void DictionaryAttackLockReset(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const DictionaryAttackLockResetResponse& callback);
+ virtual TPM_RC DictionaryAttackLockResetSync(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> DictionaryAttackParametersResponse;
+ static TPM_RC SerializeCommand_DictionaryAttackParameters(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_DictionaryAttackParameters(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void DictionaryAttackParameters(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ AuthorizationDelegate* authorization_delegate,
+ const DictionaryAttackParametersResponse& callback);
+ virtual TPM_RC DictionaryAttackParametersSync(
+ const TPMI_RH_LOCKOUT& lock_handle,
+ const std::string& lock_handle_name,
+ const UINT32& new_max_tries,
+ const UINT32& new_recovery_time,
+ const UINT32& lockout_recovery,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> PP_CommandsResponse;
+ static TPM_RC SerializeCommand_PP_Commands(
+ const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_PP_Commands(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void PP_Commands(
+ const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate,
+ const PP_CommandsResponse& callback);
+ virtual TPM_RC PP_CommandsSync(
+ const TPMI_RH_PLATFORM& auth,
+ const std::string& auth_name,
+ const TPML_CC& set_list,
+ const TPML_CC& clear_list,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> SetAlgorithmSetResponse;
+ static TPM_RC SerializeCommand_SetAlgorithmSet(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_SetAlgorithmSet(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void SetAlgorithmSet(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ AuthorizationDelegate* authorization_delegate,
+ const SetAlgorithmSetResponse& callback);
+ virtual TPM_RC SetAlgorithmSetSync(
+ const TPMI_RH_PLATFORM& auth_handle,
+ const std::string& auth_handle_name,
+ const UINT32& algorithm_set,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> FieldUpgradeStartResponse;
+ static TPM_RC SerializeCommand_FieldUpgradeStart(
+ const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_FieldUpgradeStart(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void FieldUpgradeStart(
+ const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ AuthorizationDelegate* authorization_delegate,
+ const FieldUpgradeStartResponse& callback);
+ virtual TPM_RC FieldUpgradeStartSync(
+ const TPMI_RH_PLATFORM& authorization,
+ const std::string& authorization_name,
+ const TPMI_DH_OBJECT& key_handle,
+ const std::string& key_handle_name,
+ const TPM2B_DIGEST& fu_digest,
+ const TPMT_SIGNATURE& manifest_signature,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMT_HA& next_digest,
+ const TPMT_HA& first_digest)> FieldUpgradeDataResponse;
+ static TPM_RC SerializeCommand_FieldUpgradeData(
+ const TPM2B_MAX_BUFFER& fu_data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_FieldUpgradeData(
+ const std::string& response,
+ TPMT_HA* next_digest,
+ TPMT_HA* first_digest,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void FieldUpgradeData(
+ const TPM2B_MAX_BUFFER& fu_data,
+ AuthorizationDelegate* authorization_delegate,
+ const FieldUpgradeDataResponse& callback);
+ virtual TPM_RC FieldUpgradeDataSync(
+ const TPM2B_MAX_BUFFER& fu_data,
+ TPMT_HA* next_digest,
+ TPMT_HA* first_digest,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_MAX_BUFFER& fu_data)> FirmwareReadResponse;
+ static TPM_RC SerializeCommand_FirmwareRead(
+ const UINT32& sequence_number,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_FirmwareRead(
+ const std::string& response,
+ TPM2B_MAX_BUFFER* fu_data,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void FirmwareRead(
+ const UINT32& sequence_number,
+ AuthorizationDelegate* authorization_delegate,
+ const FirmwareReadResponse& callback);
+ virtual TPM_RC FirmwareReadSync(
+ const UINT32& sequence_number,
+ TPM2B_MAX_BUFFER* fu_data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMS_CONTEXT& context)> ContextSaveResponse;
+ static TPM_RC SerializeCommand_ContextSave(
+ const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ContextSave(
+ const std::string& response,
+ TPMS_CONTEXT* context,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ContextSave(
+ const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const ContextSaveResponse& callback);
+ virtual TPM_RC ContextSaveSync(
+ const TPMI_DH_CONTEXT& save_handle,
+ const std::string& save_handle_name,
+ TPMS_CONTEXT* context,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMI_DH_CONTEXT& loaded_handle)> ContextLoadResponse;
+ static TPM_RC SerializeCommand_ContextLoad(
+ const TPMS_CONTEXT& context,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ContextLoad(
+ const std::string& response,
+ TPMI_DH_CONTEXT* loaded_handle,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ContextLoad(
+ const TPMS_CONTEXT& context,
+ AuthorizationDelegate* authorization_delegate,
+ const ContextLoadResponse& callback);
+ virtual TPM_RC ContextLoadSync(
+ const TPMS_CONTEXT& context,
+ TPMI_DH_CONTEXT* loaded_handle,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> FlushContextResponse;
+ static TPM_RC SerializeCommand_FlushContext(
+ const TPMI_DH_CONTEXT& flush_handle,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_FlushContext(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void FlushContext(
+ const TPMI_DH_CONTEXT& flush_handle,
+ AuthorizationDelegate* authorization_delegate,
+ const FlushContextResponse& callback);
+ virtual TPM_RC FlushContextSync(
+ const TPMI_DH_CONTEXT& flush_handle,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> EvictControlResponse;
+ static TPM_RC SerializeCommand_EvictControl(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_EvictControl(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void EvictControl(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ AuthorizationDelegate* authorization_delegate,
+ const EvictControlResponse& callback);
+ virtual TPM_RC EvictControlSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPMI_DH_OBJECT& object_handle,
+ const std::string& object_handle_name,
+ const TPMI_DH_PERSISTENT& persistent_handle,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMS_TIME_INFO& current_time)> ReadClockResponse;
+ static TPM_RC SerializeCommand_ReadClock(
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ReadClock(
+ const std::string& response,
+ TPMS_TIME_INFO* current_time,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ReadClock(
+ AuthorizationDelegate* authorization_delegate,
+ const ReadClockResponse& callback);
+ virtual TPM_RC ReadClockSync(
+ TPMS_TIME_INFO* current_time,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ClockSetResponse;
+ static TPM_RC SerializeCommand_ClockSet(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ClockSet(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ClockSet(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ AuthorizationDelegate* authorization_delegate,
+ const ClockSetResponse& callback);
+ virtual TPM_RC ClockSetSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const UINT64& new_time,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> ClockRateAdjustResponse;
+ static TPM_RC SerializeCommand_ClockRateAdjust(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_ClockRateAdjust(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void ClockRateAdjust(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ AuthorizationDelegate* authorization_delegate,
+ const ClockRateAdjustResponse& callback);
+ virtual TPM_RC ClockRateAdjustSync(
+ const TPMI_RH_PROVISION& auth,
+ const std::string& auth_name,
+ const TPM_CLOCK_ADJUST& rate_adjust,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPMI_YES_NO& more_data,
+ const TPMS_CAPABILITY_DATA& capability_data)> GetCapabilityResponse;
+ static TPM_RC SerializeCommand_GetCapability(
+ const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_GetCapability(
+ const std::string& response,
+ TPMI_YES_NO* more_data,
+ TPMS_CAPABILITY_DATA* capability_data,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void GetCapability(
+ const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ AuthorizationDelegate* authorization_delegate,
+ const GetCapabilityResponse& callback);
+ virtual TPM_RC GetCapabilitySync(
+ const TPM_CAP& capability,
+ const UINT32& property,
+ const UINT32& property_count,
+ TPMI_YES_NO* more_data,
+ TPMS_CAPABILITY_DATA* capability_data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> TestParmsResponse;
+ static TPM_RC SerializeCommand_TestParms(
+ const TPMT_PUBLIC_PARMS& parameters,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_TestParms(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void TestParms(
+ const TPMT_PUBLIC_PARMS& parameters,
+ AuthorizationDelegate* authorization_delegate,
+ const TestParmsResponse& callback);
+ virtual TPM_RC TestParmsSync(
+ const TPMT_PUBLIC_PARMS& parameters,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_DefineSpaceResponse;
+ static TPM_RC SerializeCommand_NV_DefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_DefineSpace(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_DefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_DefineSpaceResponse& callback);
+ virtual TPM_RC NV_DefineSpaceSync(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPM2B_AUTH& auth,
+ const TPM2B_NV_PUBLIC& public_info,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_UndefineSpaceResponse;
+ static TPM_RC SerializeCommand_NV_UndefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_UndefineSpace(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_UndefineSpace(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_UndefineSpaceResponse& callback);
+ virtual TPM_RC NV_UndefineSpaceSync(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_UndefineSpaceSpecialResponse;
+ static TPM_RC SerializeCommand_NV_UndefineSpaceSpecial(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_UndefineSpaceSpecial(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_UndefineSpaceSpecial(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_UndefineSpaceSpecialResponse& callback);
+ virtual TPM_RC NV_UndefineSpaceSpecialSync(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPMI_RH_PLATFORM& platform,
+ const std::string& platform_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_NV_PUBLIC& nv_public,
+ const TPM2B_NAME& nv_name)> NV_ReadPublicResponse;
+ static TPM_RC SerializeCommand_NV_ReadPublic(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_ReadPublic(
+ const std::string& response,
+ TPM2B_NV_PUBLIC* nv_public,
+ TPM2B_NAME* nv_name,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_ReadPublic(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadPublicResponse& callback);
+ virtual TPM_RC NV_ReadPublicSync(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ TPM2B_NV_PUBLIC* nv_public,
+ TPM2B_NAME* nv_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_WriteResponse;
+ static TPM_RC SerializeCommand_NV_Write(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_Write(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_Write(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_WriteResponse& callback);
+ virtual TPM_RC NV_WriteSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_IncrementResponse;
+ static TPM_RC SerializeCommand_NV_Increment(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_Increment(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_Increment(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_IncrementResponse& callback);
+ virtual TPM_RC NV_IncrementSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_ExtendResponse;
+ static TPM_RC SerializeCommand_NV_Extend(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_Extend(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_Extend(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ExtendResponse& callback);
+ virtual TPM_RC NV_ExtendSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_MAX_NV_BUFFER& data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_SetBitsResponse;
+ static TPM_RC SerializeCommand_NV_SetBits(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_SetBits(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_SetBits(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_SetBitsResponse& callback);
+ virtual TPM_RC NV_SetBitsSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT64& bits,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_WriteLockResponse;
+ static TPM_RC SerializeCommand_NV_WriteLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_WriteLock(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_WriteLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_WriteLockResponse& callback);
+ virtual TPM_RC NV_WriteLockSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_GlobalWriteLockResponse;
+ static TPM_RC SerializeCommand_NV_GlobalWriteLock(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_GlobalWriteLock(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_GlobalWriteLock(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_GlobalWriteLockResponse& callback);
+ virtual TPM_RC NV_GlobalWriteLockSync(
+ const TPMI_RH_PROVISION& auth_handle,
+ const std::string& auth_handle_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_MAX_NV_BUFFER& data)> NV_ReadResponse;
+ static TPM_RC SerializeCommand_NV_Read(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_Read(
+ const std::string& response,
+ TPM2B_MAX_NV_BUFFER* data,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_Read(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadResponse& callback);
+ virtual TPM_RC NV_ReadSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_MAX_NV_BUFFER* data,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_ReadLockResponse;
+ static TPM_RC SerializeCommand_NV_ReadLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_ReadLock(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_ReadLock(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ReadLockResponse& callback);
+ virtual TPM_RC NV_ReadLockSync(
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code)> NV_ChangeAuthResponse;
+ static TPM_RC SerializeCommand_NV_ChangeAuth(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_ChangeAuth(
+ const std::string& response,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_ChangeAuth(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_ChangeAuthResponse& callback);
+ virtual TPM_RC NV_ChangeAuthSync(
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_AUTH& new_auth,
+ AuthorizationDelegate* authorization_delegate);
+ typedef base::Callback<void(
+ TPM_RC response_code,
+ const TPM2B_ATTEST& certify_info,
+ const TPMT_SIGNATURE& signature)> NV_CertifyResponse;
+ static TPM_RC SerializeCommand_NV_Certify(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ std::string* serialized_command,
+ AuthorizationDelegate* authorization_delegate);
+ static TPM_RC ParseResponse_NV_Certify(
+ const std::string& response,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+ virtual void NV_Certify(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ AuthorizationDelegate* authorization_delegate,
+ const NV_CertifyResponse& callback);
+ virtual TPM_RC NV_CertifySync(
+ const TPMI_DH_OBJECT& sign_handle,
+ const std::string& sign_handle_name,
+ const TPMI_RH_NV_AUTH& auth_handle,
+ const std::string& auth_handle_name,
+ const TPMI_RH_NV_INDEX& nv_index,
+ const std::string& nv_index_name,
+ const TPM2B_DATA& qualifying_data,
+ const TPMT_SIG_SCHEME& in_scheme,
+ const UINT16& size,
+ const UINT16& offset,
+ TPM2B_ATTEST* certify_info,
+ TPMT_SIGNATURE* signature,
+ AuthorizationDelegate* authorization_delegate);
+
+ private:
+ CommandTransceiver* transceiver_;
+
+ DISALLOW_COPY_AND_ASSIGN(Tpm);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_GENERATED_H_
diff --git a/trunks/tpm_generated_test.cc b/trunks/tpm_generated_test.cc
new file mode 100644
index 0000000..6a7e15e
--- /dev/null
+++ b/trunks/tpm_generated_test.cc
@@ -0,0 +1,440 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+// Note: These tests are not generated. They test generated code.
+
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/message_loop/message_loop.h>
+#include <base/run_loop.h>
+#include <gtest/gtest.h>
+
+#include "trunks/mock_authorization_delegate.h"
+#include "trunks/mock_command_transceiver.h"
+#include "trunks/tpm_generated.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::StrictMock;
+using testing::WithArg;
+
+namespace trunks {
+
+// This test is designed to get good coverage of the different types of code
+// generated for serializing and parsing structures / unions / typedefs.
+TEST(GeneratorTest, SerializeParseStruct) {
+ TPM2B_CREATION_DATA data;
+ memset(&data, 0, sizeof(TPM2B_CREATION_DATA));
+ data.creation_data.pcr_select.count = 1;
+ data.creation_data.pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
+ data.creation_data.pcr_select.pcr_selections[0].sizeof_select = 1;
+ data.creation_data.pcr_select.pcr_selections[0].pcr_select[0] = 0;
+ data.creation_data.pcr_digest.size = 2;
+ data.creation_data.locality = 0;
+ data.creation_data.parent_name_alg = TPM_ALG_SHA256;
+ data.creation_data.parent_name.size = 3;
+ data.creation_data.parent_qualified_name.size = 4;
+ data.creation_data.outside_info.size = 5;
+ std::string buffer;
+ TPM_RC rc = Serialize_TPM2B_CREATION_DATA(data, &buffer);
+ ASSERT_EQ(TPM_RC_SUCCESS, rc);
+ EXPECT_EQ(35, buffer.size());
+ TPM2B_CREATION_DATA data2;
+ memset(&data2, 0, sizeof(TPM2B_CREATION_DATA));
+ std::string buffer_before = buffer;
+ std::string buffer_parsed;
+ rc = Parse_TPM2B_CREATION_DATA(&buffer, &data2, &buffer_parsed);
+ ASSERT_EQ(TPM_RC_SUCCESS, rc);
+ EXPECT_EQ(0, buffer.size());
+ EXPECT_EQ(buffer_before, buffer_parsed);
+ EXPECT_EQ(buffer_before.size() - 2, data2.size);
+ EXPECT_EQ(0, memcmp(&data.creation_data,
+ &data2.creation_data,
+ sizeof(TPMS_CREATION_DATA)));
+}
+
+TEST(GeneratorTest, SerializeBufferOverflow) {
+ TPM2B_MAX_BUFFER value;
+ value.size = arraysize(value.buffer) + 1;
+ std::string tmp;
+ EXPECT_EQ(TPM_RC_INSUFFICIENT, Serialize_TPM2B_MAX_BUFFER(value, &tmp));
+}
+
+TEST(GeneratorTest, ParseBufferOverflow) {
+ TPM2B_MAX_BUFFER tmp;
+ // Case 1: Sufficient source but overflow the destination.
+ std::string malformed1 = "\x10\x00";
+ malformed1 += std::string(0x1000, 'A');
+ ASSERT_GT(0x1000, sizeof(tmp.buffer));
+ EXPECT_EQ(TPM_RC_INSUFFICIENT,
+ Parse_TPM2B_MAX_BUFFER(&malformed1, &tmp, nullptr));
+ // Case 2: Sufficient destination but overflow the source.
+ std::string malformed2 = "\x00\x01";
+ EXPECT_EQ(TPM_RC_INSUFFICIENT,
+ Parse_TPM2B_MAX_BUFFER(&malformed2, &tmp, nullptr));
+}
+
+TEST(GeneratorTest, SynchronousCommand) {
+ // A hand-rolled TPM2_Startup command.
+ std::string expected_command("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0C" // size=12
+ "\x00\x00\x01\x44" // code=TPM_CC_Startup
+ "\x00\x00", // param=TPM_SU_CLEAR
+ 12);
+ std::string command_response("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0A" // size=10
+ "\x00\x00\x00\x00", // code=TPM_RC_SUCCESS
+ 10);
+ StrictMock<MockCommandTransceiver> transceiver;
+ EXPECT_CALL(transceiver, SendCommandAndWait(expected_command))
+ .WillOnce(Return(command_response));
+ StrictMock<MockAuthorizationDelegate> authorization;
+ EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
+ .WillOnce(Return(true));
+ Tpm tpm(&transceiver);
+ EXPECT_EQ(TPM_RC_SUCCESS, tpm.StartupSync(TPM_SU_CLEAR, &authorization));
+}
+
+TEST(GeneratorTest, SynchronousCommandWithError) {
+ // A hand-rolled TPM2_Startup command.
+ std::string expected_command("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0C" // size=12
+ "\x00\x00\x01\x44" // code=TPM_CC_Startup
+ "\x00\x00", // param=TPM_SU_CLEAR
+ 12);
+ std::string command_response("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0A" // size=10
+ "\x00\x00\x01\x01", // code=TPM_RC_FAILURE
+ 10);
+ StrictMock<MockCommandTransceiver> transceiver;
+ EXPECT_CALL(transceiver, SendCommandAndWait(expected_command))
+ .WillOnce(Return(command_response));
+ StrictMock<MockAuthorizationDelegate> authorization;
+ EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
+ .WillOnce(Return(true));
+ Tpm tpm(&transceiver);
+ EXPECT_EQ(TPM_RC_FAILURE, tpm.StartupSync(TPM_SU_CLEAR, &authorization));
+}
+
+TEST(GeneratorTest, SynchronousCommandResponseTest) {
+ std::string auth_in(10, 'A');
+ std::string auth_out(10, 'B');
+ std::string auth_size("\x00\x00\x00\x0A", 4);
+ std::string handle_in("\x40\x00\x00\x07", 4); // primary_handle = TPM_RH_NULL
+ std::string handle_out("\x80\x00\x00\x01", 4); // out_handle
+ std::string sensitive("\x00\x05" // sensitive.size = 5
+ "\x00\x01" // sensitive.auth.size = 1
+ "\x61" // sensitive.auth.buffer[0] = 0x65
+ "\x00\x00", // sensitive.data.size = 0
+ 7);
+ std::string public_data("\x00\x12" // public.size = 18
+ "\x00\x25" // public.type = TPM_ALG_SYMCIPHER
+ "\x00\x0B" // public.name_alg = SHA256
+ "\x00\x00\x00\x00"
+ "\x00\x00" // public.auth_policy.size = 0
+ "\x00\x06" // public.sym.alg = TPM_ALG_AES
+ "\x00\x80" // public.sym.key_bits = 128
+ "\x00\x43" // public.sym.mode = TPM_ALG_CFB
+ "\x00\x00", // public.unique.size = 0
+ 20);
+ std::string outside("\x00\x00", 2); // outside_info.size = 0
+ std::string pcr_select("\x00\x00\x00\x00", 4); // pcr_select.size = 0
+
+ std::string data("\x00\x0F" // creation_data.size = 15
+ "\x00\x00\x00\x00" // creation.pcr = 0
+ "\x00\x00" // creation.digest.size = 0
+ "\x00" // creation.locality = 0
+ "\x00\x00" // creation.parent_alg = 0
+ "\x00\x00" // creation.parent_name.size = 0
+ "\x00\x00"
+ "\x00\x00", // creation.outside.size = 0
+ 17);
+ std::string hash("\x00\x01"
+ "\x62", 3);
+ std::string ticket("\x80\x02" // tag = TPM_ST_SESSIONS
+ "\x40\x00\x00\x07" // parent = TPM_RH_NULL
+ "\x00\x00", 8);
+ std::string name("\x00\x03" "KEY", 5);
+ std::string parameter_size("\x00\x00\x00\x35", 4); // param_size = 38
+
+ std::string command_tag("\x80\x02" // tag = TPM_ST_SESSIONS
+ "\x00\x00\x00\x3D" // size = 61
+ "\x00\x00\x01\x31", // code = TPM_CC_CreatePrimary
+ 10);
+ std::string response_tag("\x80\x02" // tag = TPM_ST_SESSIONS
+ "\x00\x00\x00\x51" // size = 79
+ "\x00\x00\x00\x00", // rc = TPM_RC_SUCCESS
+ 10);
+
+ std::string expected_command = command_tag + handle_in + auth_size + auth_in +
+ sensitive + public_data + outside + pcr_select;
+ std::string command_response = response_tag + handle_out + parameter_size +
+ public_data + data + hash + ticket + name +
+ auth_out;
+
+ StrictMock<MockCommandTransceiver> transceiver;
+ EXPECT_CALL(transceiver, SendCommandAndWait(expected_command))
+ .WillOnce(Return(command_response));
+ StrictMock<MockAuthorizationDelegate> authorization;
+ EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(auth_in), Return(true)));
+ EXPECT_CALL(authorization, CheckResponseAuthorization(_, auth_out))
+ .WillOnce(Return(true));
+ EXPECT_CALL(authorization, EncryptCommandParameter(_))
+ .WillOnce(Return(true));
+ EXPECT_CALL(authorization, DecryptResponseParameter(_))
+ .WillOnce(Return(true));
+
+ TPM2B_SENSITIVE_CREATE in_sensitive;
+ in_sensitive.size = 5;
+ in_sensitive.sensitive.user_auth.size = 1;
+ in_sensitive.sensitive.user_auth.buffer[0] = 'a';
+ in_sensitive.sensitive.data.size = 0;
+ TPM2B_PUBLIC in_public;
+ in_public.size = 18;
+ in_public.public_area.type = TPM_ALG_SYMCIPHER;
+ in_public.public_area.name_alg = TPM_ALG_SHA256;
+ in_public.public_area.object_attributes = 0;
+ in_public.public_area.auth_policy.size = 0;
+ in_public.public_area.parameters.sym_detail.sym.algorithm = TPM_ALG_AES;
+ in_public.public_area.parameters.sym_detail.sym.key_bits.aes = 128;
+ in_public.public_area.parameters.sym_detail.sym.mode.aes = TPM_ALG_CFB;
+ in_public.public_area.unique.sym.size = 0;
+ TPM2B_DATA outside_info;
+ outside_info.size = 0;
+ TPML_PCR_SELECTION create_pcr;
+ create_pcr.count = 0;
+
+ TPM_HANDLE key_handle;
+ TPM2B_PUBLIC out_public;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ TPM2B_NAME key_name;
+
+ Tpm tpm(&transceiver);
+ TPM_RC rc = tpm.CreatePrimarySync(trunks::TPM_RH_NULL,
+ "",
+ in_sensitive,
+ in_public,
+ outside_info,
+ create_pcr,
+ &key_handle,
+ &out_public,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket,
+ &key_name,
+ &authorization);
+ ASSERT_EQ(rc, TPM_RC_SUCCESS);
+ EXPECT_EQ(key_handle, 0x80000001);
+ EXPECT_EQ(out_public.size, 18);
+ EXPECT_EQ(creation_data.size, 15);
+ EXPECT_EQ(creation_hash.size, 1);
+ EXPECT_EQ(creation_hash.buffer[0], 'b');
+ EXPECT_EQ(creation_ticket.tag, 0x8002);
+ EXPECT_EQ(creation_ticket.hierarchy, 0x40000007);
+ EXPECT_EQ(creation_ticket.digest.size, 0);
+ EXPECT_EQ(key_name.size, 3);
+ EXPECT_EQ(key_name.name[0], 'K');
+ EXPECT_EQ(key_name.name[1], 'E');
+ EXPECT_EQ(key_name.name[2], 'Y');
+}
+
+// A fixture for asynchronous command flow tests.
+class CommandFlowTest : public testing::Test {
+ public:
+ CommandFlowTest() : response_code_(TPM_RC_SUCCESS) {}
+ ~CommandFlowTest() override {}
+
+ void StartupCallback(TPM_RC response_code) {
+ response_code_ = response_code;
+ }
+
+ void CertifyCallback(TPM_RC response_code,
+ const TPM2B_ATTEST& certify_info,
+ const TPMT_SIGNATURE& signature) {
+ response_code_ = response_code;
+ signed_data_ = StringFrom_TPM2B_ATTEST(certify_info);
+ signature_ = StringFrom_TPM2B_PUBLIC_KEY_RSA(
+ signature.signature.rsassa.sig);
+ }
+
+ protected:
+ void Run() {
+ base::RunLoop run_loop;
+ run_loop.RunUntilIdle();
+ }
+
+ base::MessageLoop message_loop_;
+ TPM_RC response_code_;
+ std::string signature_;
+ std::string signed_data_;
+};
+
+// A functor for posting command responses. This is different than invoking the
+// callback directly (e.g. via InvokeArgument) in that the original call will
+// return before the response callback is invoked. This more closely matches how
+// this code is expected to work when integrated.
+class PostResponse {
+ public:
+ explicit PostResponse(const std::string& response) : response_(response) {}
+ void operator() (const base::Callback<void(const std::string&)>& callback) {
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(callback, response_));
+ }
+
+ private:
+ std::string response_;
+};
+
+// A functor to handle fake encryption / decryption of parameters.
+class Encryptor {
+ public:
+ Encryptor(const std::string& expected_input, const std::string& output)
+ : expected_input_(expected_input),
+ output_(output) {}
+ bool operator() (std::string* value) {
+ EXPECT_EQ(expected_input_, *value);
+ value->assign(output_);
+ return true;
+ }
+
+ private:
+ std::string expected_input_;
+ std::string output_;
+};
+
+TEST_F(CommandFlowTest, SimpleCommandFlow) {
+ // A hand-rolled TPM2_Startup command.
+ std::string expected_command("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0C" // size=12
+ "\x00\x00\x01\x44" // code=TPM_CC_Startup
+ "\x00\x00", // param=TPM_SU_CLEAR
+ 12);
+ std::string command_response("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0A" // size=10
+ "\x00\x00\x00\x00", // code=TPM_RC_SUCCESS
+ 10);
+ StrictMock<MockCommandTransceiver> transceiver;
+ EXPECT_CALL(transceiver, SendCommand(expected_command, _))
+ .WillOnce(WithArg<1>(Invoke(PostResponse(command_response))));
+ StrictMock<MockAuthorizationDelegate> authorization;
+ EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
+ .WillOnce(Return(true));
+ Tpm tpm(&transceiver);
+ response_code_ = TPM_RC_FAILURE;
+ tpm.Startup(TPM_SU_CLEAR,
+ &authorization,
+ base::Bind(&CommandFlowTest::StartupCallback,
+ base::Unretained(this)));
+ Run();
+ EXPECT_EQ(TPM_RC_SUCCESS, response_code_);
+}
+
+TEST_F(CommandFlowTest, SimpleCommandFlowWithError) {
+ // A hand-rolled TPM2_Startup command.
+ std::string expected_command("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0C" // size=12
+ "\x00\x00\x01\x44" // code=TPM_CC_Startup
+ "\x00\x00", // param=TPM_SU_CLEAR
+ 12);
+ std::string command_response("\x80\x01" // tag=TPM_ST_NO_SESSIONS
+ "\x00\x00\x00\x0A" // size=10
+ "\x00\x00\x01\x01", // code=TPM_RC_FAILURE
+ 10);
+ StrictMock<MockCommandTransceiver> transceiver;
+ EXPECT_CALL(transceiver, SendCommand(expected_command, _))
+ .WillOnce(WithArg<1>(Invoke(PostResponse(command_response))));
+ StrictMock<MockAuthorizationDelegate> authorization;
+ EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
+ .WillOnce(Return(true));
+ Tpm tpm(&transceiver);
+ tpm.Startup(TPM_SU_CLEAR,
+ &authorization,
+ base::Bind(&CommandFlowTest::StartupCallback,
+ base::Unretained(this)));
+ Run();
+ EXPECT_EQ(TPM_RC_FAILURE, response_code_);
+}
+
+// This test is designed to get good coverage of the different types of code
+// generated for command / response processing. It covers:
+// - input handles
+// - authorization
+// - multiple input and output parameters
+// - parameter encryption and decryption
+TEST_F(CommandFlowTest, FullCommandFlow) {
+ // A hand-rolled TPM2_Certify command.
+ std::string auth_in(10, 'A');
+ std::string auth_out(20, 'B');
+ std::string user_data("\x00\x0C" "ct_user_data", 14);
+ std::string scheme("\x00\x10", 2); // scheme=TPM_ALG_NULL
+ std::string signed_data("\x00\x0E" "ct_signed_data", 16);
+ std::string signature("\x00\x14" // sig_scheme=RSASSA
+ "\x00\x0B" // hash_scheme=SHA256
+ "\x00\x09" // signature size
+ "signature", // signature bytes
+ 15);
+ std::string expected_command("\x80\x02" // tag=TPM_ST_SESSIONS
+ "\x00\x00\x00\x30" // size=48
+ "\x00\x00\x01\x48" // code=TPM_CC_Certify
+ "\x11\x22\x33\x44" // @objectHandle
+ "\x55\x66\x77\x88" // @signHandle
+ "\x00\x00\x00\x0A", // auth_size=10
+ 22);
+ expected_command += auth_in + user_data + scheme;
+ std::string command_response("\x80\x02" // tag=TPM_ST_SESSIONS
+ "\x00\x00\x00\x41" // size=65
+ "\x00\x00\x00\x00" // code=TPM_RC_SUCCESS
+ "\x00\x00\x00\x1F", // param_size=31
+ 14);
+ command_response += signed_data + signature + auth_out;
+
+ StrictMock<MockCommandTransceiver> transceiver;
+ EXPECT_CALL(transceiver, SendCommand(expected_command, _))
+ .WillOnce(WithArg<1>(Invoke(PostResponse(command_response))));
+ StrictMock<MockAuthorizationDelegate> authorization;
+ EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(auth_in), Return(true)));
+ EXPECT_CALL(authorization, CheckResponseAuthorization(_, auth_out))
+ .WillOnce(Return(true));
+ EXPECT_CALL(authorization, EncryptCommandParameter(_))
+ .WillOnce(Invoke(Encryptor("pt_user_data", "ct_user_data")));
+ EXPECT_CALL(authorization, DecryptResponseParameter(_))
+ .WillOnce(Invoke(Encryptor("ct_signed_data", "pt_signed_data")));
+
+ TPMT_SIG_SCHEME null_scheme;
+ null_scheme.scheme = TPM_ALG_NULL;
+ null_scheme.details.rsassa.hash_alg = TPM_ALG_SHA256;
+ Tpm tpm(&transceiver);
+ tpm.Certify(0x11223344u, "object_handle",
+ 0x55667788u, "sign_handle",
+ Make_TPM2B_DATA("pt_user_data"),
+ null_scheme,
+ &authorization,
+ base::Bind(&CommandFlowTest::CertifyCallback,
+ base::Unretained(this)));
+ Run();
+ ASSERT_EQ(TPM_RC_SUCCESS, response_code_);
+ EXPECT_EQ("pt_signed_data", signed_data_);
+ EXPECT_EQ("signature", signature_);
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_handle.cc b/trunks/tpm_handle.cc
new file mode 100644
index 0000000..e47e06d
--- /dev/null
+++ b/trunks/tpm_handle.cc
@@ -0,0 +1,97 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/tpm_handle.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <base/callback.h>
+#include <base/logging.h>
+#include <base/posix/eintr_wrapper.h>
+
+namespace {
+
+const char kTpmDevice[] = "/dev/tpm0";
+const uint32_t kTpmBufferSize = 4096;
+const int kInvalidFileDescriptor = -1;
+
+} // namespace
+
+namespace trunks {
+
+TpmHandle::TpmHandle() : fd_(kInvalidFileDescriptor) {}
+
+TpmHandle::~TpmHandle() {
+ int result = IGNORE_EINTR(close(fd_));
+ if (result == -1) {
+ PLOG(ERROR) << "TPM: couldn't close " << kTpmDevice;
+ }
+ LOG(INFO) << "TPM: " << kTpmDevice << " closed successfully";
+}
+
+bool TpmHandle::Init() {
+ if (fd_ != kInvalidFileDescriptor) {
+ VLOG(1) << "Tpm already initialized.";
+ return true;
+ }
+ fd_ = HANDLE_EINTR(open(kTpmDevice, O_RDWR));
+ if (fd_ == kInvalidFileDescriptor) {
+ PLOG(ERROR) << "TPM: Error opening tpm0 file descriptor at " << kTpmDevice;
+ return false;
+ }
+ LOG(INFO) << "TPM: " << kTpmDevice << " opened successfully";
+ return true;
+}
+
+void TpmHandle::SendCommand(const std::string& command,
+ const ResponseCallback& callback) {
+ callback.Run(SendCommandAndWait(command));
+}
+
+std::string TpmHandle::SendCommandAndWait(const std::string& command) {
+ std::string response;
+ TPM_RC result = SendCommandInternal(command, &response);
+ if (result != TPM_RC_SUCCESS) {
+ response = CreateErrorResponse(result);
+ }
+ return response;
+}
+
+TPM_RC TpmHandle::SendCommandInternal(const std::string& command,
+ std::string* response) {
+ CHECK_NE(fd_, kInvalidFileDescriptor);
+ int result = HANDLE_EINTR(write(fd_, command.data(), command.length()));
+ if (result < 0) {
+ PLOG(ERROR) << "TPM: Error writing to TPM handle.";
+ return TRUNKS_RC_WRITE_ERROR;
+ }
+ if (static_cast<size_t>(result) != command.length()) {
+ LOG(ERROR) << "TPM: Error writing to TPM handle: " << result << " vs "
+ << command.length();
+ return TRUNKS_RC_WRITE_ERROR;
+ }
+ char response_buf[kTpmBufferSize];
+ result = HANDLE_EINTR(read(fd_, response_buf, kTpmBufferSize));
+ if (result < 0) {
+ PLOG(ERROR) << "TPM: Error reading from TPM handle.";
+ return TRUNKS_RC_READ_ERROR;
+ }
+ response->assign(response_buf, static_cast<size_t>(result));
+ return TPM_RC_SUCCESS;
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_handle.h b/trunks/tpm_handle.h
new file mode 100644
index 0000000..3aa626f
--- /dev/null
+++ b/trunks/tpm_handle.h
@@ -0,0 +1,63 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_HANDLE_H_
+#define TRUNKS_TPM_HANDLE_H_
+
+#include "trunks/command_transceiver.h"
+
+#include <string>
+
+#include "trunks/error_codes.h"
+
+namespace trunks {
+
+// Sends commands to a TPM device via a handle to /dev/tpm0. All commands are
+// sent synchronously. The SendCommand method is supported but does not return
+// until a response is received and the callback has been called. Command and
+// response data are opaque to this class; it performs no validation.
+//
+// Example:
+// TpmHandle handle;
+// if (!handle.Init()) {...}
+// std::string response = handle.SendCommandAndWait(command);
+class TpmHandle : public CommandTransceiver {
+ public:
+ TpmHandle();
+ ~TpmHandle() override;
+
+ // Initializes a TpmHandle instance. This method must be called successfully
+ // before any other method. Returns true on success.
+ bool Init() override;
+
+ // CommandTranceiver methods.
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) override;
+ std::string SendCommandAndWait(const std::string& command) override;
+
+ private:
+ // Writes a |command| to /dev/tpm0 and reads the |response|. Returns
+ // TPM_RC_SUCCESS on success.
+ TPM_RC SendCommandInternal(const std::string& command, std::string* response);
+
+ int fd_; // A file descriptor for /dev/tpm0.
+
+ DISALLOW_COPY_AND_ASSIGN(TpmHandle);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_HANDLE_H_
diff --git a/trunks/tpm_simulator_handle.cc b/trunks/tpm_simulator_handle.cc
new file mode 100644
index 0000000..5e26651
--- /dev/null
+++ b/trunks/tpm_simulator_handle.cc
@@ -0,0 +1,115 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/tpm_simulator_handle.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <base/callback.h>
+#include <base/logging.h>
+#include <base/posix/eintr_wrapper.h>
+
+namespace {
+
+const char kTpmSimRequestFile[] = "/dev/tpm-req";
+const char kTpmSimResponseFile[] = "/dev/tpm-resp";
+const uint32_t kTpmBufferSize = 4096;
+const int kInvalidFileDescriptor = -1;
+
+} // namespace
+
+namespace trunks {
+
+TpmSimulatorHandle::TpmSimulatorHandle() :
+ req_fd_(kInvalidFileDescriptor), resp_fd_(kInvalidFileDescriptor) {}
+
+TpmSimulatorHandle::~TpmSimulatorHandle() {
+ int result = IGNORE_EINTR(close(req_fd_));
+ if (result == -1) {
+ PLOG(ERROR) << "TPM: couldn't close " << kTpmSimRequestFile;
+ } else {
+ LOG(INFO) << "TPM: " << kTpmSimRequestFile << " closed successfully";
+ }
+ result = IGNORE_EINTR(close(resp_fd_));
+ if (result == -1) {
+ PLOG(ERROR) << "TPM: couldn't close " << kTpmSimResponseFile;
+ } else {
+ LOG(INFO) << "TPM: " << kTpmSimResponseFile << " closed successfully";
+ }
+}
+
+bool TpmSimulatorHandle::Init() {
+ if (req_fd_ == kInvalidFileDescriptor) {
+ req_fd_ = HANDLE_EINTR(open("/dev/tpm-req", O_RDWR));
+ if (req_fd_ == kInvalidFileDescriptor) {
+ PLOG(ERROR) << "TPM: Error opening file descriptor at "
+ << kTpmSimRequestFile;
+ return false;
+ }
+ LOG(INFO) << "TPM: " << kTpmSimRequestFile << " opened successfully";
+ }
+ if (resp_fd_ == kInvalidFileDescriptor) {
+ resp_fd_ = HANDLE_EINTR(open("/dev/tpm-resp", O_RDWR));
+ if (resp_fd_ == kInvalidFileDescriptor) {
+ PLOG(ERROR) << "TPM: Error opening file descriptor at "
+ << kTpmSimResponseFile;
+ return false;
+ }
+ LOG(INFO) << "TPM: " << kTpmSimResponseFile << " opened successfully";
+ }
+ return true;
+}
+
+void TpmSimulatorHandle::SendCommand(const std::string& command,
+ const ResponseCallback& callback) {
+ callback.Run(SendCommandAndWait(command));
+}
+
+std::string TpmSimulatorHandle::SendCommandAndWait(const std::string& command) {
+ std::string response;
+ TPM_RC result = SendCommandInternal(command, &response);
+ if (result != TPM_RC_SUCCESS) {
+ response = CreateErrorResponse(result);
+ }
+ return response;
+}
+
+TPM_RC TpmSimulatorHandle::SendCommandInternal(const std::string& command,
+ std::string* response) {
+ CHECK_NE(req_fd_, kInvalidFileDescriptor);
+ CHECK_NE(resp_fd_, kInvalidFileDescriptor);
+ int result = HANDLE_EINTR(write(req_fd_, command.data(), command.length()));
+ if (result < 0) {
+ PLOG(ERROR) << "TPM: Error writing to TPM simulator request handle.";
+ return TRUNKS_RC_WRITE_ERROR;
+ }
+ if (static_cast<size_t>(result) != command.length()) {
+ LOG(ERROR) << "TPM: Error writing to TPM simulator request handle: "
+ << result << " vs " << command.length();
+ return TRUNKS_RC_WRITE_ERROR;
+ }
+ char response_buf[kTpmBufferSize];
+ result = HANDLE_EINTR(read(resp_fd_, response_buf, kTpmBufferSize));
+ if (result < 0) {
+ PLOG(ERROR) << "TPM: Error reading from TPM simulator response handle.";
+ return TRUNKS_RC_READ_ERROR;
+ }
+ response->assign(response_buf, static_cast<size_t>(result));
+ return TPM_RC_SUCCESS;
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_simulator_handle.h b/trunks/tpm_simulator_handle.h
new file mode 100644
index 0000000..1b4d230
--- /dev/null
+++ b/trunks/tpm_simulator_handle.h
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_SIMULATOR_HANDLE_H_
+#define TRUNKS_TPM_SIMULATOR_HANDLE_H_
+
+#include "trunks/command_transceiver.h"
+
+#include <string>
+
+#include "trunks/error_codes.h"
+
+namespace trunks {
+
+// Sends command requests to a software TPM via a handle to /dev/tpm-req.
+// Receives command responses via a handle to /dev/tpm-resp. All commands are
+// sent synchronously. The SendCommand method is supported but does not return
+// until a response is received and the callback has been called. Command and
+// response data are opaque to this class; it performs no validation.
+//
+// Example:
+// TpmSimulatorHandle handle;
+// if (!handle.Init()) {...}
+// std::string response = handle.SendCommandAndWait(command);
+class TpmSimulatorHandle : public CommandTransceiver {
+ public:
+ TpmSimulatorHandle();
+ ~TpmSimulatorHandle() override;
+
+ // Initializes a TpmSimulatorHandle instance. This method must be called
+ // successfully before any other method. Returns true on success.
+ bool Init() override;
+
+ // CommandTranceiver methods.
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) override;
+ std::string SendCommandAndWait(const std::string& command) override;
+
+ private:
+ // Writes a |command| to /dev/tpm-req and reads the |response| from
+ // /dev/tpm-resp. Returns TPM_RC_SUCCESS on success.
+ TPM_RC SendCommandInternal(const std::string& command, std::string* response);
+
+ int req_fd_; // A file descriptor for /dev/tpm-req.
+ int resp_fd_; // A file descriptor for /dev/tpm-resp.
+
+ DISALLOW_COPY_AND_ASSIGN(TpmSimulatorHandle);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_SIMULATOR_HANDLE_H_
diff --git a/trunks/tpm_state.h b/trunks/tpm_state.h
new file mode 100644
index 0000000..21443de
--- /dev/null
+++ b/trunks/tpm_state.h
@@ -0,0 +1,94 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_STATE_H_
+#define TRUNKS_TPM_STATE_H_
+
+#include <base/macros.h>
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+// TpmState is an interface which provides access to TPM state information.
+class TRUNKS_EXPORT TpmState {
+ public:
+ TpmState() {}
+ virtual ~TpmState() {}
+
+ // Initializes based on the current TPM state. This method must be called once
+ // before any other method. It may be called multiple times to refresh the
+ // state information.
+ virtual TPM_RC Initialize() = 0;
+
+ // Returns true iff TPMA_PERMANENT:ownerAuthSet is set.
+ virtual bool IsOwnerPasswordSet() = 0;
+
+ // Returns true iff TPMA_PERMANENT:endorsementAuthSet is set.
+ virtual bool IsEndorsementPasswordSet() = 0;
+
+ // Returns true iff TPMA_PERMANENT:lockoutAuthSet is set.
+ virtual bool IsLockoutPasswordSet() = 0;
+
+ // Returns true iff owner, endorsement and lockout passwords are set.
+ virtual bool IsOwned() = 0;
+
+ // Returns true iff TPMA_PERMANENT:inLockout is set.
+ virtual bool IsInLockout() = 0;
+
+ // Returns true iff TPMA_STARTUP_CLEAR:phEnable is set.
+ virtual bool IsPlatformHierarchyEnabled() = 0;
+
+ // Returns true iff TPMA_STARTUP_CLEAR:shEnable is set.
+ virtual bool IsStorageHierarchyEnabled() = 0;
+
+ // Returns true iff TPMA_STARTUP_CLEAR:ehEnable is set.
+ virtual bool IsEndorsementHierarchyEnabled() = 0;
+
+ // Returns true iff shEnable and ehEnable are set and phEnable is clear.
+ virtual bool IsEnabled() = 0;
+
+ // Returns true iff TPMA_STARTUP_CLEAR:orderly is set.
+ virtual bool WasShutdownOrderly() = 0;
+
+ // Returns true iff the TPM supports RSA-2048 keys.
+ virtual bool IsRSASupported() = 0;
+
+ // Returns true iff the TPM supports the ECC NIST P-256 curve.
+ virtual bool IsECCSupported() = 0;
+
+ // Returns the current value of the Lockout counter.
+ virtual uint32_t GetLockoutCounter() = 0;
+
+ // Returns the maximum lockout failures allowed before the TPM goes into
+ // lockout.
+ virtual uint32_t GetLockoutThreshold() = 0;
+
+ // Returns the number of seconds before the lockout counter will decrement.
+ virtual uint32_t GetLockoutInterval() = 0;
+
+ // Returns the number of seconds after a LockoutAuth failure before
+ // LockoutAuth can be used again.
+ virtual uint32_t GetLockoutRecovery() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TpmState);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_STATE_H_
diff --git a/trunks/tpm_state_impl.cc b/trunks/tpm_state_impl.cc
new file mode 100644
index 0000000..ca9f7b0
--- /dev/null
+++ b/trunks/tpm_state_impl.cc
@@ -0,0 +1,246 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/tpm_state_impl.h"
+
+#include <base/logging.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory.h"
+
+namespace {
+
+// From definition of TPMA_PERMANENT.
+const trunks::TPMA_PERMANENT kOwnerAuthSetMask = 1U;
+const trunks::TPMA_PERMANENT kEndorsementAuthSetMask = 1U << 1;
+const trunks::TPMA_PERMANENT kLockoutAuthSetMask = 1U << 2;
+const trunks::TPMA_PERMANENT kInLockoutMask = 1U << 9;
+
+// From definition of TPMA_STARTUP_CLEAR.
+const trunks::TPMA_STARTUP_CLEAR kPlatformHierarchyMask = 1U;
+const trunks::TPMA_STARTUP_CLEAR kStorageHierarchyMask = 1U << 1;
+const trunks::TPMA_STARTUP_CLEAR kEndorsementHierarchyMask = 1U << 2;
+const trunks::TPMA_STARTUP_CLEAR kOrderlyShutdownMask = 1U << 31;
+
+// From definition of TPMA_ALGORITHM
+const trunks::TPMA_ALGORITHM kAsymmetricAlgMask = 1U;
+
+} // namespace
+
+namespace trunks {
+
+TpmStateImpl::TpmStateImpl(const TrunksFactory& factory)
+ : factory_(factory),
+ initialized_(false),
+ permanent_flags_(0),
+ startup_clear_flags_(0),
+ rsa_flags_(0),
+ ecc_flags_(0) {
+}
+
+TpmStateImpl::~TpmStateImpl() {}
+
+TPM_RC TpmStateImpl::Initialize() {
+ TPM_RC result = GetTpmProperty(TPM_PT_PERMANENT, &permanent_flags_);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting permanent flags: " << GetErrorString(result);
+ return result;
+ }
+ result = GetTpmProperty(TPM_PT_STARTUP_CLEAR, &startup_clear_flags_);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting startup flags: " << GetErrorString(result);
+ return result;
+ }
+ result = GetTpmProperty(TPM_PT_LOCKOUT_COUNTER, &lockout_counter_);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting lockout counter: " << GetErrorString(result);
+ return result;
+ }
+ result = GetTpmProperty(TPM_PT_MAX_AUTH_FAIL, &lockout_threshold_);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting lockout threshold: " << GetErrorString(result);
+ return result;
+ }
+ result = GetTpmProperty(TPM_PT_LOCKOUT_INTERVAL, &lockout_interval_);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting lockout interval: " << GetErrorString(result);
+ return result;
+ }
+ result = GetTpmProperty(TPM_PT_LOCKOUT_RECOVERY, &lockout_recovery_);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting lockout recovery: " << GetErrorString(result);
+ return result;
+ }
+
+ TPMI_YES_NO more_data;
+ TPMS_CAPABILITY_DATA capability_data;
+ result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS,
+ TPM_ALG_RSA,
+ 1, // There is only one value.
+ &more_data,
+ &capability_data,
+ nullptr);
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ if (capability_data.capability != TPM_CAP_ALGS ||
+ capability_data.data.algorithms.count != 1) {
+ LOG(ERROR) << __func__ << ": Unexpected capability data.";
+ return SAPI_RC_MALFORMED_RESPONSE;
+ }
+ if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_RSA) {
+ rsa_flags_ =
+ capability_data.data.algorithms.alg_properties[0].alg_properties;
+ }
+ result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS,
+ TPM_ALG_ECC,
+ 1, // There is only one value.
+ &more_data,
+ &capability_data,
+ nullptr);
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ if (capability_data.capability != TPM_CAP_ALGS ||
+ capability_data.data.algorithms.count != 1) {
+ LOG(ERROR) << __func__ << ": Unexpected capability data.";
+ return SAPI_RC_MALFORMED_RESPONSE;
+ }
+ if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_ECC) {
+ ecc_flags_ =
+ capability_data.data.algorithms.alg_properties[0].alg_properties;
+ }
+ initialized_ = true;
+ return TPM_RC_SUCCESS;
+}
+
+bool TpmStateImpl::IsOwnerPasswordSet() {
+ CHECK(initialized_);
+ return ((permanent_flags_ & kOwnerAuthSetMask) == kOwnerAuthSetMask);
+}
+
+bool TpmStateImpl::IsEndorsementPasswordSet() {
+ CHECK(initialized_);
+ return ((permanent_flags_ & kEndorsementAuthSetMask) ==
+ kEndorsementAuthSetMask);
+}
+
+bool TpmStateImpl::IsLockoutPasswordSet() {
+ CHECK(initialized_);
+ return ((permanent_flags_ & kLockoutAuthSetMask) == kLockoutAuthSetMask);
+}
+
+bool TpmStateImpl::IsOwned() {
+ return (IsOwnerPasswordSet() &&
+ IsEndorsementPasswordSet() &&
+ IsLockoutPasswordSet());
+}
+
+bool TpmStateImpl::IsInLockout() {
+ CHECK(initialized_);
+ return ((permanent_flags_ & kInLockoutMask) == kInLockoutMask);
+}
+
+bool TpmStateImpl::IsPlatformHierarchyEnabled() {
+ CHECK(initialized_);
+ return ((startup_clear_flags_ & kPlatformHierarchyMask) ==
+ kPlatformHierarchyMask);
+}
+
+bool TpmStateImpl::IsStorageHierarchyEnabled() {
+ CHECK(initialized_);
+ return ((startup_clear_flags_ & kStorageHierarchyMask) ==
+ kStorageHierarchyMask);
+}
+
+bool TpmStateImpl::IsEndorsementHierarchyEnabled() {
+ CHECK(initialized_);
+ return ((startup_clear_flags_ & kEndorsementHierarchyMask) ==
+ kEndorsementHierarchyMask);
+}
+
+bool TpmStateImpl::IsEnabled() {
+ return (!IsPlatformHierarchyEnabled() &&
+ IsStorageHierarchyEnabled() &&
+ IsEndorsementHierarchyEnabled());
+}
+
+bool TpmStateImpl::WasShutdownOrderly() {
+ CHECK(initialized_);
+ return ((startup_clear_flags_ & kOrderlyShutdownMask) ==
+ kOrderlyShutdownMask);
+}
+
+bool TpmStateImpl::IsRSASupported() {
+ CHECK(initialized_);
+ return ((rsa_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
+}
+
+bool TpmStateImpl::IsECCSupported() {
+ CHECK(initialized_);
+ return ((ecc_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
+}
+
+uint32_t TpmStateImpl::GetLockoutCounter() {
+ CHECK(initialized_);
+ return lockout_counter_;
+}
+
+uint32_t TpmStateImpl::GetLockoutThreshold() {
+ CHECK(initialized_);
+ return lockout_threshold_;
+}
+
+uint32_t TpmStateImpl::GetLockoutInterval() {
+ CHECK(initialized_);
+ return lockout_interval_;
+}
+
+uint32_t TpmStateImpl::GetLockoutRecovery() {
+ CHECK(initialized_);
+ return lockout_recovery_;
+}
+
+TPM_RC TpmStateImpl::GetTpmProperty(uint32_t property,
+ uint32_t* value) {
+ CHECK(value);
+ TPMI_YES_NO more_data;
+ TPMS_CAPABILITY_DATA capability_data;
+ TPM_RC result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ property,
+ 1, // Only one property.
+ &more_data,
+ &capability_data,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ if (capability_data.capability != TPM_CAP_TPM_PROPERTIES ||
+ capability_data.data.tpm_properties.count != 1 ||
+ capability_data.data.tpm_properties.tpm_property[0].property !=
+ property) {
+ LOG(ERROR) << __func__ << ": Unexpected capability data.";
+ return SAPI_RC_MALFORMED_RESPONSE;
+ }
+ *value = capability_data.data.tpm_properties.tpm_property[0].value;
+ return TPM_RC_SUCCESS;
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_state_impl.h b/trunks/tpm_state_impl.h
new file mode 100644
index 0000000..14247ff
--- /dev/null
+++ b/trunks/tpm_state_impl.h
@@ -0,0 +1,78 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_STATE_IMPL_H_
+#define TRUNKS_TPM_STATE_IMPL_H_
+
+#include "trunks/tpm_state.h"
+
+#include <base/macros.h>
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class TrunksFactory;
+
+// TpmStateImpl is the default implementation of the TpmState interface.
+class TRUNKS_EXPORT TpmStateImpl : public TpmState {
+ public:
+ explicit TpmStateImpl(const TrunksFactory& factory);
+ ~TpmStateImpl() override;
+
+ // TpmState methods.
+ TPM_RC Initialize() override;
+ bool IsOwnerPasswordSet() override;
+ bool IsEndorsementPasswordSet() override;
+ bool IsLockoutPasswordSet() override;
+ bool IsOwned() override;
+ bool IsInLockout() override;
+ bool IsPlatformHierarchyEnabled() override;
+ bool IsStorageHierarchyEnabled() override;
+ bool IsEndorsementHierarchyEnabled() override;
+ bool IsEnabled() override;
+ bool WasShutdownOrderly() override;
+ bool IsRSASupported() override;
+ bool IsECCSupported() override;
+ uint32_t GetLockoutCounter() override;
+ uint32_t GetLockoutThreshold() override;
+ uint32_t GetLockoutInterval() override;
+ uint32_t GetLockoutRecovery() override;
+
+ private:
+ // This helped method calls Tpm2_GetCapability with TPM_CAP_TPM_PROPERTIES
+ // and |property|. The returned structure is validated, and the value returned
+ // is stored in the out argument |value|. Returns TPM_RC_SUCCESS on success.
+ TPM_RC GetTpmProperty(uint32_t property, uint32_t* value);
+
+ const TrunksFactory& factory_;
+ bool initialized_;
+ TPMA_PERMANENT permanent_flags_;
+ TPMA_STARTUP_CLEAR startup_clear_flags_;
+ uint32_t lockout_counter_;
+ uint32_t lockout_threshold_;
+ uint32_t lockout_interval_;
+ uint32_t lockout_recovery_;
+ TPMA_ALGORITHM rsa_flags_;
+ TPMA_ALGORITHM ecc_flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(TpmStateImpl);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_STATE_IMPL_H_
diff --git a/trunks/tpm_state_test.cc b/trunks/tpm_state_test.cc
new file mode 100644
index 0000000..5833607
--- /dev/null
+++ b/trunks/tpm_state_test.cc
@@ -0,0 +1,384 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "trunks/mock_tpm.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/tpm_state_impl.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::WithArgs;
+
+namespace trunks {
+
+// From definition of TPMA_STARTUP_CLEAR.
+const trunks::TPMA_STARTUP_CLEAR kPlatformHierarchyMask = 1U;
+
+// A test fixture for TpmState tests.
+class TpmStateTest : public testing::Test {
+ public:
+ TpmStateTest() {}
+ ~TpmStateTest() override {}
+
+ void SetUp() override {
+ factory_.set_tpm(&mock_tpm_);
+ permanent_data_ = GetValidCapabilityData(TPM_PT_PERMANENT, 0);
+ startup_clear_data_ = GetValidCapabilityData(TPM_PT_STARTUP_CLEAR, 0);
+ rsa_data_ = GetValidAlgorithmData(TPM_ALG_RSA, 0);
+ ecc_data_ = GetValidAlgorithmData(TPM_ALG_ECC, 0);
+ lockout_counter_ = GetValidCapabilityData(TPM_PT_LOCKOUT_COUNTER, 0);
+ lockout_threshold_ = GetValidCapabilityData(TPM_PT_MAX_AUTH_FAIL, 0);
+ lockout_interval_ = GetValidCapabilityData(TPM_PT_LOCKOUT_INTERVAL, 0);
+ lockout_recovery_ = GetValidCapabilityData(TPM_PT_LOCKOUT_RECOVERY, 0);
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_PERMANENT, 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLivePermanent)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_STARTUP_CLEAR, 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveStartupClear)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_ALGS,
+ TPM_ALG_RSA, 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveRSA)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_ALGS,
+ TPM_ALG_ECC, 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveECC)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_LOCKOUT_COUNTER,
+ 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveLockoutCounter)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_MAX_AUTH_FAIL,
+ 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveLockoutThreshold)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_LOCKOUT_INTERVAL,
+ 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveLockoutInterval)));
+ EXPECT_CALL(mock_tpm_, GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_LOCKOUT_RECOVERY,
+ 1, _, _, _))
+ .WillRepeatedly(WithArgs<4>(
+ Invoke(this, &TpmStateTest::GetLiveLockoutRecovery)));
+ }
+
+ TPM_RC GetLivePermanent(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = permanent_data_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveStartupClear(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = startup_clear_data_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveRSA(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = rsa_data_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveECC(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = ecc_data_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveLockoutCounter(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = lockout_counter_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveLockoutThreshold(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = lockout_threshold_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveLockoutInterval(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = lockout_interval_;
+ return TPM_RC_SUCCESS;
+ }
+ TPM_RC GetLiveLockoutRecovery(TPMS_CAPABILITY_DATA* capability_data) {
+ *capability_data = lockout_recovery_;
+ return TPM_RC_SUCCESS;
+ }
+
+ protected:
+ TPMS_CAPABILITY_DATA GetValidCapabilityData(TPM_PT property, UINT32 value) {
+ TPMS_CAPABILITY_DATA data;
+ memset(&data, 0, sizeof(TPMS_CAPABILITY_DATA));
+ data.capability = TPM_CAP_TPM_PROPERTIES;
+ data.data.tpm_properties.count = 1;
+ data.data.tpm_properties.tpm_property[0].property = property;
+ data.data.tpm_properties.tpm_property[0].value = value;
+ return data;
+ }
+
+ TPMS_CAPABILITY_DATA GetValidAlgorithmData(TPM_ALG_ID alg_id, UINT32 value) {
+ TPMS_CAPABILITY_DATA data;
+ memset(&data, 0, sizeof(TPMS_CAPABILITY_DATA));
+ data.capability = TPM_CAP_ALGS;
+ data.data.tpm_properties.count = 1;
+ data.data.algorithms.alg_properties[0].alg = alg_id;
+ data.data.algorithms.alg_properties[0].alg_properties = value;
+ return data;
+ }
+
+ TrunksFactoryForTest factory_;
+ NiceMock<MockTpm> mock_tpm_;
+ TPMS_CAPABILITY_DATA permanent_data_;
+ TPMS_CAPABILITY_DATA startup_clear_data_;
+ TPMS_CAPABILITY_DATA rsa_data_;
+ TPMS_CAPABILITY_DATA ecc_data_;
+ TPMS_CAPABILITY_DATA lockout_counter_;
+ TPMS_CAPABILITY_DATA lockout_threshold_;
+ TPMS_CAPABILITY_DATA lockout_interval_;
+ TPMS_CAPABILITY_DATA lockout_recovery_;
+};
+
+TEST(TpmState_DeathTest, NotInitialized) {
+ TrunksFactoryForTest factory;
+ TpmStateImpl tpm_state(factory);
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsOwnerPasswordSet(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsEndorsementPasswordSet(),
+ "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsLockoutPasswordSet(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsOwned(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsInLockout(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsPlatformHierarchyEnabled(),
+ "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsStorageHierarchyEnabled(),
+ "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsEndorsementHierarchyEnabled(),
+ "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsEnabled(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.WasShutdownOrderly(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsRSASupported(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsECCSupported(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutCounter(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutThreshold(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutInterval(), "Check failed");
+ EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutRecovery(), "Check failed");
+}
+
+TEST_F(TpmStateTest, FlagsClear) {
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
+ EXPECT_FALSE(tpm_state.IsOwnerPasswordSet());
+ EXPECT_FALSE(tpm_state.IsEndorsementPasswordSet());
+ EXPECT_FALSE(tpm_state.IsLockoutPasswordSet());
+ EXPECT_FALSE(tpm_state.IsInLockout());
+ EXPECT_FALSE(tpm_state.IsOwned());
+ EXPECT_FALSE(tpm_state.IsPlatformHierarchyEnabled());
+ EXPECT_FALSE(tpm_state.IsStorageHierarchyEnabled());
+ EXPECT_FALSE(tpm_state.IsEndorsementHierarchyEnabled());
+ EXPECT_FALSE(tpm_state.IsEnabled());
+ EXPECT_FALSE(tpm_state.WasShutdownOrderly());
+ EXPECT_FALSE(tpm_state.IsRSASupported());
+ EXPECT_FALSE(tpm_state.IsECCSupported());
+ EXPECT_EQ(0, tpm_state.GetLockoutCounter());
+ EXPECT_EQ(0, tpm_state.GetLockoutThreshold());
+ EXPECT_EQ(0, tpm_state.GetLockoutInterval());
+ EXPECT_EQ(0, tpm_state.GetLockoutRecovery());
+}
+
+TEST_F(TpmStateTest, FlagsSet) {
+ uint32_t lockout_counter = 5;
+ uint32_t lockout_threshold = 8;
+ uint32_t lockout_interval = 1200;
+ uint32_t lockout_recovery = 84600;
+ permanent_data_.data.tpm_properties.tpm_property[0].value = ~0U;
+ startup_clear_data_.data.tpm_properties.tpm_property[0].value = ~0U;
+ lockout_counter_.data.tpm_properties.tpm_property[0].value = lockout_counter;
+ lockout_threshold_.data.tpm_properties.tpm_property[0].value =
+ lockout_threshold;
+ lockout_interval_.data.tpm_properties.tpm_property[0].value =
+ lockout_interval;
+ lockout_recovery_.data.tpm_properties.tpm_property[0].value =
+ lockout_recovery;
+ rsa_data_.data.algorithms.alg_properties[0].alg_properties = ~0U;
+ ecc_data_.data.algorithms.alg_properties[0].alg_properties = ~0U;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
+ EXPECT_TRUE(tpm_state.IsOwnerPasswordSet());
+ EXPECT_TRUE(tpm_state.IsEndorsementPasswordSet());
+ EXPECT_TRUE(tpm_state.IsLockoutPasswordSet());
+ EXPECT_TRUE(tpm_state.IsOwned());
+ EXPECT_TRUE(tpm_state.IsInLockout());
+ EXPECT_TRUE(tpm_state.IsPlatformHierarchyEnabled());
+ EXPECT_TRUE(tpm_state.IsStorageHierarchyEnabled());
+ EXPECT_TRUE(tpm_state.IsEndorsementHierarchyEnabled());
+ EXPECT_FALSE(tpm_state.IsEnabled());
+ EXPECT_TRUE(tpm_state.WasShutdownOrderly());
+ EXPECT_TRUE(tpm_state.IsRSASupported());
+ EXPECT_TRUE(tpm_state.IsECCSupported());
+ EXPECT_EQ(lockout_counter, tpm_state.GetLockoutCounter());
+ EXPECT_EQ(lockout_threshold, tpm_state.GetLockoutThreshold());
+ EXPECT_EQ(lockout_interval, tpm_state.GetLockoutInterval());
+ EXPECT_EQ(lockout_recovery, tpm_state.GetLockoutRecovery());
+}
+
+TEST_F(TpmStateTest, EnabledTpm) {
+ startup_clear_data_.data.tpm_properties.tpm_property[0].value =
+ ~kPlatformHierarchyMask;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
+ EXPECT_FALSE(tpm_state.IsPlatformHierarchyEnabled());
+ EXPECT_TRUE(tpm_state.IsStorageHierarchyEnabled());
+ EXPECT_TRUE(tpm_state.IsEndorsementHierarchyEnabled());
+ EXPECT_TRUE(tpm_state.IsEnabled());
+ EXPECT_TRUE(tpm_state.WasShutdownOrderly());
+}
+
+TEST_F(TpmStateTest, BadResponsePermanentCapabilityType) {
+ permanent_data_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseStartupClearCapabilityType) {
+ startup_clear_data_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutCounterCapabilityType) {
+ lockout_counter_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutThresholdCapabilityType) {
+ lockout_threshold_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutIntervalCapabilityType) {
+ lockout_interval_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutRecoveryCapabilityType) {
+ lockout_recovery_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseRSAAlgCapabilityType) {
+ rsa_data_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseECCAlgCapabilityType) {
+ ecc_data_.capability = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponsePermanentPropertyCount) {
+ permanent_data_.data.tpm_properties.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseStartupClearPropertyCount) {
+ startup_clear_data_.data.tpm_properties.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutCounterPropertyCount) {
+ lockout_counter_.data.tpm_properties.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutThresholdPropertyCount) {
+ lockout_threshold_.data.tpm_properties.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutIntervalPropertyCount) {
+ lockout_interval_.data.tpm_properties.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutRecoveryPropertyCount) {
+ lockout_recovery_.data.tpm_properties.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseRSAAlgPropertyCount) {
+ rsa_data_.data.algorithms.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseECCAlgPropertyCount) {
+ ecc_data_.data.algorithms.count = 0;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponsePermanentPropertyType) {
+ permanent_data_.data.tpm_properties.tpm_property[0].property = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseStartupClearPropertyType) {
+ startup_clear_data_.data.tpm_properties.tpm_property[0].property = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutCounterPropertyType) {
+ lockout_counter_.data.tpm_properties.tpm_property[0].property = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutThresholdPropertyType) {
+ lockout_threshold_.data.tpm_properties.tpm_property[0].property = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutIntervalPropertyType) {
+ lockout_interval_.data.tpm_properties.tpm_property[0].property = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+TEST_F(TpmStateTest, BadResponseLockoutRecoveryPropertyType) {
+ lockout_recovery_.data.tpm_properties.tpm_property[0].property = 0xFFFFF;
+ TpmStateImpl tpm_state(factory_);
+ EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_utility.h b/trunks/tpm_utility.h
new file mode 100644
index 0000000..c2db557
--- /dev/null
+++ b/trunks/tpm_utility.h
@@ -0,0 +1,304 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_UTILITY_H_
+#define TRUNKS_TPM_UTILITY_H_
+
+#include <string>
+
+#include <base/macros.h>
+
+#include "trunks/hmac_session.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+// These handles will be used by TpmUtility to create storage root keys.
+const TPMI_DH_PERSISTENT kRSAStorageRootKey = PERSISTENT_FIRST;
+const TPMI_DH_PERSISTENT kECCStorageRootKey = PERSISTENT_FIRST + 1;
+const TPMI_DH_PERSISTENT kSaltingKey = PERSISTENT_FIRST + 2;
+
+// This value to used to specify that no pcr are needed in the creation data
+// for a key.
+const int kNoCreationPCR = -1;
+
+// An interface which provides convenient methods for common TPM operations.
+class TRUNKS_EXPORT TpmUtility {
+ public:
+ enum AsymmetricKeyUsage {
+ kDecryptKey,
+ kSignKey,
+ kDecryptAndSignKey
+ };
+
+ TpmUtility() {}
+ virtual ~TpmUtility() {}
+
+ // Synchronously performs a TPM startup sequence and self tests. Typically
+ // this is done by the platform firmware. Returns the result of the startup
+ // and self-tests or, if already started, just the result of the self-tests.
+ virtual TPM_RC Startup() = 0;
+
+ // This method removes all TPM context associated with a specific Owner.
+ // As part of this process, it resets the SPS to a new random value, and
+ // clears ownerAuth, endorsementAuth and lockoutAuth.
+ // NOTE: This method needs to be called before InitializeTPM.
+ virtual TPM_RC Clear() = 0;
+
+ // Synchronously performs a TPM shutdown operation. It should always be
+ // successful.
+ virtual void Shutdown() = 0;
+
+ // Synchronously prepares a TPM for use by Chromium OS. Typically this is done
+ // by the platform firmware and, in that case, this method has no effect.
+ virtual TPM_RC InitializeTpm() = 0;
+
+ // Synchronously allocates the PCRs in the TPM. Currently we allocate
+ // the first 16 PCRs to use the SHA-256 hash algorithm.
+ // NOTE: PCR allocation only takes place at the next TPM_Startup call.
+ // NOTE: This command needs platform authorization and PP assertion.
+ virtual TPM_RC AllocatePCR(const std::string& platform_password) = 0;
+
+ // Synchronously takes ownership of the TPM with the given passwords as
+ // authorization values.
+ virtual TPM_RC TakeOwnership(const std::string& owner_password,
+ const std::string& endorsement_password,
+ const std::string& lockout_password) = 0;
+
+ // Stir the tpm random generation module with some random entropy data.
+ // |delegate| specifies an optional authorization delegate to be used.
+ virtual TPM_RC StirRandom(const std::string& entropy_data,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method returns |num_bytes| of random data generated by the tpm.
+ // |delegate| specifies an optional authorization delegate to be used.
+ virtual TPM_RC GenerateRandom(size_t num_bytes,
+ AuthorizationDelegate* delegate,
+ std::string* random_data) = 0;
+
+ // This method extends the pcr specified by |pcr_index| with the SHA256
+ // hash of |extend_data|. The exact action performed is
+ // TPM2_PCR_Extend(Sha256(extend_data));
+ // |delegate| specifies an optional authorization delegate to be used.
+ virtual TPM_RC ExtendPCR(int pcr_index,
+ const std::string& extend_data,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method reads the pcr specified by |pcr_index| and returns its value
+ // in |pcr_value|. NOTE: it assumes we are using SHA256 as our hash alg.
+ virtual TPM_RC ReadPCR(int pcr_index, std::string* pcr_value) = 0;
+
+ // This method performs an encryption operation using a LOADED RSA key
+ // referrenced by its handle |key_handle|. The |plaintext| is then encrypted
+ // to give us the |ciphertext|. |scheme| refers to the encryption scheme
+ // to be used. By default keys use OAEP, but can also use TPM_ALG_RSAES.
+ // |delegate| specifies an optional authorization delegate to be used.
+ virtual TPM_RC AsymmetricEncrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* ciphertext) = 0;
+
+ // This method performs a decyption operating using a loaded RSA key
+ // referenced by its handle |key_handle|. The |ciphertext| is then decrypted
+ // to give us the |plaintext|. |scheme| refers to the decryption scheme
+ // used. By default it is OAEP, but TPM_ALG_RSAES can be specified.
+ // |delegate| is an AuthorizationDelegate used to authorize this command.
+ virtual TPM_RC AsymmetricDecrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& ciphertext,
+ AuthorizationDelegate* delegate,
+ std::string* plaintext) = 0;
+
+ // This method takes an unrestricted signing key referenced by |key_handle|
+ // and uses it to sign the hash of |plaintext|. The signature produced is
+ // returned using the |signature| argument. |scheme| is used to specify the
+ // signature scheme used. By default it is TPM_ALG_RSASSA, but TPM_ALG_RSAPPS
+ // can be specified. |hash_alg| is the algorithm used in the signing
+ // operation. It is by default TPM_ALG_SHA256.
+ // |delegate| is an AuthorizationDelegate used to authorize this command.
+ virtual TPM_RC Sign(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* signature) = 0;
+
+ // This method verifies that the signature produced on the plaintext was
+ // performed by |key_handle|. |scheme| and |hash| refer to the signature
+ // scheme used to sign the hash of |plaintext| and produce the signature.
+ // This value is by default TPM_ALG_RSASSA with TPM_ALG_SHA256 but can take
+ // the value of TPM_ALG_RSAPPS with other hash algorithms supported by the
+ // tpm. Returns TPM_RC_SUCCESS when the signature is correct.
+ // |delegate| specifies an optional authorization delegate to be used.
+ virtual TPM_RC Verify(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ const std::string& signature,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method is used to check if a key was created in the TPM. |key_handle|
+ // refers to a loaded Tpm2.0 object, and |creation_blob| is the blob
+ // generated when the object was created. Returns TPM_RC_SUCCESS iff the
+ // object was created in the TPM.
+ virtual TPM_RC CertifyCreation(TPM_HANDLE key_handle,
+ const std::string& creation_blob) = 0;
+
+ // This method is used to change the authorization value associated with a
+ // |key_handle| to |new_password|. |delegate| is an AuthorizationDelegate
+ // that is loaded with the old authorization value of |key_handle|.
+ // When |key_blob| is not null, it is populated with the new encrypted key
+ // blob. Note: the key must be unloaded and reloaded to use the
+ // new authorization value.
+ virtual TPM_RC ChangeKeyAuthorizationData(TPM_HANDLE key_handle,
+ const std::string& new_password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) = 0;
+
+ // This method imports an external RSA key of |key_type| into the TPM.
+ // |modulus| and |prime_factor| are interpreted as raw bytes in big-endian
+ // order. If the out argument |key_blob| is not null, it is populated with
+ // the imported key, which can then be loaded into the TPM.
+ virtual TPM_RC ImportRSAKey(AsymmetricKeyUsage key_type,
+ const std::string& modulus,
+ uint32_t public_exponent,
+ const std::string& prime_factor,
+ const std::string& password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) = 0;
+
+ // This method uses the TPM to generates an RSA key of type |key_type|.
+ // |modulus_bits| is used to specify the size of the modulus, and
+ // |public_exponent| specifies the exponent of the key. After this function
+ // terminates, |key_blob| contains a key blob that can be loaded into the TPM.
+ // |policy_digest| specifies an optional policy to use to authorize this key.
+ // |use_only_policy_authorization| specifies if we can use HmacSession in
+ // addition to PolicySession to authorize use of this key.
+ // |creation_pcr_index| allows the caller to specify a pcr value to include
+ // in the creation data. If no pcr are needed in the creation data, this
+ // argument can take the value of kNoCreationPCR.
+ // If the |creation_blob| out param is defined, it will contain the
+ // serialized creation structures generated by the TPM.
+ // This can be used to verify the state of the TPM during key creation.
+ // NOTE: if |use_only_policy_authorization| is set to true,
+ // parameter_encryption must be disabled when the key is used.
+ virtual TPM_RC CreateRSAKeyPair(AsymmetricKeyUsage key_type,
+ int modulus_bits,
+ uint32_t public_exponent,
+ const std::string& password,
+ const std::string& policy_digest,
+ bool use_only_policy_authorization,
+ int creation_pcr_index,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob,
+ std::string* creation_blob) = 0;
+
+ // This method loads a pregenerated TPM key into the TPM. |key_blob| contains
+ // the blob returned by a key creation function. The loaded key's handle is
+ // returned using |key_handle|.
+ virtual TPM_RC LoadKey(const std::string& key_blob,
+ AuthorizationDelegate* delegate,
+ TPM_HANDLE* key_handle) = 0;
+
+ // This function sets |name| to the name of the object referenced by
+ // |handle|. This function only works on Transient and Permanent objects.
+ virtual TPM_RC GetKeyName(TPM_HANDLE handle, std::string* name) = 0;
+
+ // This function returns the public area of a handle in the tpm.
+ virtual TPM_RC GetKeyPublicArea(TPM_HANDLE handle,
+ TPMT_PUBLIC* public_data) = 0;
+
+ // This method seals |data_to_seal| to the TPM. The |sealed_data| can be
+ // retreived by fulfilling the policy represented by |policy_digest|.
+ virtual TPM_RC SealData(const std::string& data_to_seal,
+ const std::string& policy_digest,
+ AuthorizationDelegate* delegate,
+ std::string* sealed_data) = 0;
+
+ // This method is used to retrieve data that was sealed to the TPM.
+ // |sealed_data| refers to sealed data returned from SealData.
+ virtual TPM_RC UnsealData(const std::string& sealed_data,
+ AuthorizationDelegate* delegate,
+ std::string* unsealed_data) = 0;
+
+ // This method sets up a given HmacSession with parameter encryption set to
+ // true. Returns an TPM_RC_SUCCESS on success.
+ virtual TPM_RC StartSession(HmacSession* session) = 0;
+
+ // This method uses a trial session to compute the |policy_digest| when
+ // the policy is bound to a given |pcr_value| at |pcr_index|. If |pcr_value|
+ // is the empty string, this method uses the currect value of the pcr.
+ virtual TPM_RC GetPolicyDigestForPcrValue(int pcr_index,
+ const std::string& pcr_value,
+ std::string* policy_digest) = 0;
+
+ // This method defines a non-volatile storage area in the TPM, referenced
+ // by |index| of size |num_bytes|. This command needs owner authorization.
+ // By default non-volatile space created is unlocked and anyone can write to
+ // it. The space can be permanently locked for writing by calling the
+ // LockNVSpace method.
+ virtual TPM_RC DefineNVSpace(uint32_t index,
+ size_t num_bytes,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method destroys the non-volatile space referred to by |index|.
+ // This command needs owner authorization.
+ virtual TPM_RC DestroyNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method locks the non-volatile space referred to by |index|. After a
+ // non-volatile space has been locked, it cannot be written to. Locked spaces
+ // can still be freely read. This command needs owner authorization.
+ virtual TPM_RC LockNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method writes |nvram_data| to the non-volatile space referenced by
+ // |index|, at |offset| bytes from the start of the non-volatile space.
+ virtual TPM_RC WriteNVSpace(uint32_t index,
+ uint32_t offset,
+ const std::string& nvram_data,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This method reads |num_bytes| of data from the |offset| located at the
+ // non-volatile space defined by |index|. This method returns an error if
+ // |length| + |offset| is larger than the size of the defined non-volatile
+ // space.
+ virtual TPM_RC ReadNVSpace(uint32_t index,
+ uint32_t offset,
+ size_t num_bytes,
+ std::string* nvram_data,
+ AuthorizationDelegate* delegate) = 0;
+
+ // This function sets |name| to the name of the non-volatile space referenced
+ // by |index|.
+ virtual TPM_RC GetNVSpaceName(uint32_t index, std::string* name) = 0;
+
+ // This function returns the public area of an non-volatile space defined in
+ // the TPM.
+ virtual TPM_RC GetNVSpacePublicArea(uint32_t index,
+ TPMS_NV_PUBLIC* public_data) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TpmUtility);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_UTILITY_H_
diff --git a/trunks/tpm_utility_impl.cc b/trunks/tpm_utility_impl.cc
new file mode 100644
index 0000000..dfecc90
--- /dev/null
+++ b/trunks/tpm_utility_impl.cc
@@ -0,0 +1,1798 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/tpm_utility_impl.h"
+
+#include <base/logging.h>
+#include <base/memory/scoped_ptr.h>
+#include <base/sha1.h>
+#include <base/stl_util.h>
+#include <crypto/secure_hash.h>
+#include <crypto/sha2.h>
+#include <openssl/aes.h>
+#include <openssl/rand.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/blob_parser.h"
+#include "trunks/error_codes.h"
+#include "trunks/hmac_authorization_delegate.h"
+#include "trunks/hmac_session.h"
+#include "trunks/policy_session.h"
+#include "trunks/scoped_key_handle.h"
+#include "trunks/tpm_constants.h"
+#include "trunks/tpm_state.h"
+#include "trunks/trunks_factory.h"
+
+namespace {
+
+const char kPlatformPassword[] = "cros-platform";
+const char kWellKnownPassword[] = "cros-password";
+const size_t kMaxPasswordLength = 32;
+// The below maximum is defined in TPM 2.0 Library Spec Part 2 Section 13.1
+const uint32_t kMaxNVSpaceIndex = (1<<24) - 1;
+
+// Returns a serialized representation of the unmodified handle. This is useful
+// for predefined handle values, like TPM_RH_OWNER. For details on what types of
+// handles use this name formula see Table 3 in the TPM 2.0 Library Spec Part 1
+// (Section 16 - Names).
+std::string NameFromHandle(trunks::TPM_HANDLE handle) {
+ std::string name;
+ trunks::Serialize_TPM_HANDLE(handle, &name);
+ return name;
+}
+
+std::string HashString(const std::string& plaintext,
+ trunks::TPM_ALG_ID hash_alg) {
+ switch (hash_alg) {
+ case trunks::TPM_ALG_SHA1:
+ return base::SHA1HashString(plaintext);
+ case trunks::TPM_ALG_SHA256:
+ return crypto::SHA256HashString(plaintext);
+ }
+ NOTREACHED();
+ return std::string();
+}
+
+} // namespace
+
+namespace trunks {
+
+TpmUtilityImpl::TpmUtilityImpl(const TrunksFactory& factory)
+ : factory_(factory) {}
+
+TpmUtilityImpl::~TpmUtilityImpl() {
+}
+
+TPM_RC TpmUtilityImpl::Startup() {
+ TPM_RC result = TPM_RC_SUCCESS;
+ Tpm* tpm = factory_.GetTpm();
+ result = tpm->StartupSync(TPM_SU_CLEAR, nullptr);
+ // Ignore TPM_RC_INITIALIZE, that means it was already started.
+ if (result && result != TPM_RC_INITIALIZE) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ result = tpm->SelfTestSync(YES /* Full test. */, nullptr);
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::Clear() {
+ TPM_RC result = TPM_RC_SUCCESS;
+ scoped_ptr<AuthorizationDelegate> password_delegate(
+ factory_.GetPasswordAuthorization(""));
+ result = factory_.GetTpm()->ClearSync(TPM_RH_PLATFORM,
+ NameFromHandle(TPM_RH_PLATFORM),
+ password_delegate.get());
+ // If there was an error in the initialization, platform auth is in a bad
+ // state.
+ if (result == TPM_RC_AUTH_MISSING) {
+ scoped_ptr<AuthorizationDelegate> authorization(
+ factory_.GetPasswordAuthorization(kPlatformPassword));
+ result = factory_.GetTpm()->ClearSync(TPM_RH_PLATFORM,
+ NameFromHandle(TPM_RH_PLATFORM),
+ authorization.get());
+ }
+ if (GetFormatOneError(result) == TPM_RC_BAD_AUTH) {
+ LOG(INFO) << "Clear failed because of BAD_AUTH. This probably means "
+ << "that the TPM was already initialized.";
+ return result;
+ }
+ if (result) {
+ LOG(ERROR) << "Failed to clear the TPM: " << GetErrorString(result);
+ }
+ return result;
+}
+
+void TpmUtilityImpl::Shutdown() {
+ TPM_RC return_code = factory_.GetTpm()->ShutdownSync(TPM_SU_CLEAR, nullptr);
+ if (return_code && return_code != TPM_RC_INITIALIZE) {
+ // This should not happen, but if it does, there is nothing we can do.
+ LOG(ERROR) << "Error shutting down: " << GetErrorString(return_code);
+ }
+}
+
+TPM_RC TpmUtilityImpl::InitializeTpm() {
+ TPM_RC result = TPM_RC_SUCCESS;
+ scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
+ result = tpm_state->Initialize();
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ // Warn about various unexpected conditions.
+ if (!tpm_state->WasShutdownOrderly()) {
+ LOG(WARNING) << "WARNING: The last TPM shutdown was not orderly.";
+ }
+ if (tpm_state->IsInLockout()) {
+ LOG(WARNING) << "WARNING: The TPM is currently in lockout.";
+ }
+
+ // We expect the firmware has already locked down the platform hierarchy. If
+ // it hasn't, do it now.
+ if (tpm_state->IsPlatformHierarchyEnabled()) {
+ scoped_ptr<AuthorizationDelegate> empty_password(
+ factory_.GetPasswordAuthorization(""));
+ result = SetHierarchyAuthorization(TPM_RH_PLATFORM,
+ kPlatformPassword,
+ empty_password.get());
+ if (GetFormatOneError(result) == TPM_RC_BAD_AUTH) {
+ // Most likely the platform password has already been set.
+ result = TPM_RC_SUCCESS;
+ }
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ result = AllocatePCR(kPlatformPassword);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ scoped_ptr<AuthorizationDelegate> authorization(
+ factory_.GetPasswordAuthorization(kPlatformPassword));
+ result = DisablePlatformHierarchy(authorization.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::AllocatePCR(const std::string& platform_password) {
+ TPM_RC result;
+ TPML_PCR_SELECTION pcr_allocation;
+ pcr_allocation.count = 1;
+ pcr_allocation.pcr_selections[0].hash = TPM_ALG_SHA256;
+ pcr_allocation.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
+ pcr_allocation.pcr_selections[0].pcr_select[0] = 0xff;
+ pcr_allocation.pcr_selections[0].pcr_select[1] = 0xff;
+ scoped_ptr<AuthorizationDelegate> platform_delegate(
+ factory_.GetPasswordAuthorization(platform_password));
+ TPMI_YES_NO allocation_success;
+ uint32_t max_pcr;
+ uint32_t size_needed;
+ uint32_t size_available;
+ result = factory_.GetTpm()->PCR_AllocateSync(TPM_RH_PLATFORM,
+ NameFromHandle(TPM_RH_PLATFORM),
+ pcr_allocation,
+ &allocation_success,
+ &max_pcr,
+ &size_needed,
+ &size_available,
+ platform_delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error allocating pcr: " << GetErrorString(result);
+ return result;
+ }
+ if (allocation_success != YES) {
+ LOG(ERROR) << "PCR allocation unsuccessful.";
+ return TPM_RC_FAILURE;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::TakeOwnership(const std::string& owner_password,
+ const std::string& endorsement_password,
+ const std::string& lockout_password) {
+ // First we set the storage hierarchy authorization to the well know default
+ // password.
+ TPM_RC result = TPM_RC_SUCCESS;
+ result = SetKnownOwnerPassword(kWellKnownPassword);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error injecting known password: " << GetErrorString(result);
+ return result;
+ }
+
+ result = CreateStorageRootKeys(kWellKnownPassword);
+ if (result) {
+ LOG(ERROR) << "Error creating SRKs: " << GetErrorString(result);
+ return result;
+ }
+ result = CreateSaltingKey(kWellKnownPassword);
+ if (result) {
+ LOG(ERROR) << "Error creating salting key: "
+ << GetErrorString(result);
+ return result;
+ }
+
+ scoped_ptr<HmacSession> session = factory_.GetHmacSession();
+ result = session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error initializing AuthorizationSession: "
+ << GetErrorString(result);
+ return result;
+ }
+ scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
+ result = tpm_state->Initialize();
+ session->SetEntityAuthorizationValue("");
+ session->SetFutureAuthorizationValue(endorsement_password);
+ if (!tpm_state->IsEndorsementPasswordSet()) {
+ result = SetHierarchyAuthorization(TPM_RH_ENDORSEMENT,
+ endorsement_password,
+ session->GetDelegate());
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ }
+ session->SetFutureAuthorizationValue(lockout_password);
+ if (!tpm_state->IsLockoutPasswordSet()) {
+ result = SetHierarchyAuthorization(TPM_RH_LOCKOUT,
+ lockout_password,
+ session->GetDelegate());
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ }
+ // We take ownership of owner hierarchy last.
+ session->SetEntityAuthorizationValue(kWellKnownPassword);
+ session->SetFutureAuthorizationValue(owner_password);
+ result = SetHierarchyAuthorization(TPM_RH_OWNER,
+ owner_password,
+ session->GetDelegate());
+ if ((GetFormatOneError(result) == TPM_RC_BAD_AUTH) &&
+ tpm_state->IsOwnerPasswordSet()) {
+ LOG(WARNING) << "Error changing owner password. This probably because "
+ << "ownership is already taken.";
+ return TPM_RC_SUCCESS;
+ } else if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error changing owner authorization: "
+ << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::StirRandom(const std::string& entropy_data,
+ AuthorizationDelegate* delegate) {
+ std::string digest = crypto::SHA256HashString(entropy_data);
+ TPM2B_SENSITIVE_DATA random_bytes = Make_TPM2B_SENSITIVE_DATA(digest);
+ return factory_.GetTpm()->StirRandomSync(random_bytes, delegate);
+}
+
+TPM_RC TpmUtilityImpl::GenerateRandom(size_t num_bytes,
+ AuthorizationDelegate* delegate,
+ std::string* random_data) {
+ CHECK(random_data);
+ size_t bytes_left = num_bytes;
+ random_data->clear();
+ TPM_RC rc;
+ TPM2B_DIGEST digest;
+ while (bytes_left > 0) {
+ rc = factory_.GetTpm()->GetRandomSync(bytes_left,
+ &digest,
+ delegate);
+ if (rc) {
+ LOG(ERROR) << "Error getting random data from tpm.";
+ return rc;
+ }
+ random_data->append(StringFrom_TPM2B_DIGEST(digest));
+ bytes_left -= digest.size;
+ }
+ CHECK_EQ(random_data->size(), num_bytes);
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::ExtendPCR(int pcr_index,
+ const std::string& extend_data,
+ AuthorizationDelegate* delegate) {
+ if (pcr_index < 0 || pcr_index >= IMPLEMENTATION_PCR) {
+ LOG(ERROR) << "Using a PCR index that isnt implemented.";
+ return TPM_RC_FAILURE;
+ }
+ TPM_HANDLE pcr_handle = HR_PCR + pcr_index;
+ std::string pcr_name = NameFromHandle(pcr_handle);
+ TPML_DIGEST_VALUES digests;
+ digests.count = 1;
+ digests.digests[0].hash_alg = TPM_ALG_SHA256;
+ crypto::SHA256HashString(extend_data,
+ digests.digests[0].digest.sha256,
+ crypto::kSHA256Length);
+ return factory_.GetTpm()->PCR_ExtendSync(pcr_handle,
+ pcr_name,
+ digests,
+ delegate);
+}
+
+TPM_RC TpmUtilityImpl::ReadPCR(int pcr_index, std::string* pcr_value) {
+ TPML_PCR_SELECTION pcr_select_in;
+ uint32_t pcr_update_counter;
+ TPML_PCR_SELECTION pcr_select_out;
+ TPML_DIGEST pcr_values;
+ // This process of selecting pcrs is highlighted in TPM 2.0 Library Spec
+ // Part 2 (Section 10.5 - PCR structures).
+ uint8_t pcr_select_index = pcr_index / 8;
+ uint8_t pcr_select_byte = 1 << (pcr_index % 8);
+ pcr_select_in.count = 1;
+ pcr_select_in.pcr_selections[0].hash = TPM_ALG_SHA256;
+ pcr_select_in.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
+ pcr_select_in.pcr_selections[0].pcr_select[pcr_select_index] =
+ pcr_select_byte;
+
+ TPM_RC rc = factory_.GetTpm()->PCR_ReadSync(pcr_select_in,
+ &pcr_update_counter,
+ &pcr_select_out,
+ &pcr_values,
+ nullptr);
+ if (rc) {
+ LOG(INFO) << "Error trying to read a pcr: " << GetErrorString(rc);
+ return rc;
+ }
+ if (pcr_select_out.count != 1 ||
+ pcr_select_out.pcr_selections[0].sizeof_select <
+ (pcr_select_index + 1) ||
+ pcr_select_out.pcr_selections[0].pcr_select[pcr_select_index] !=
+ pcr_select_byte) {
+ LOG(ERROR) << "TPM did not return the requested PCR";
+ return TPM_RC_FAILURE;
+ }
+ CHECK_GE(pcr_values.count, 1U);
+ pcr_value->assign(StringFrom_TPM2B_DIGEST(pcr_values.digests[0]));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::AsymmetricEncrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* ciphertext) {
+ TPMT_RSA_DECRYPT in_scheme;
+ if (hash_alg == TPM_ALG_NULL) {
+ hash_alg = TPM_ALG_SHA256;
+ }
+ if (scheme == TPM_ALG_RSAES) {
+ in_scheme.scheme = TPM_ALG_RSAES;
+ } else if (scheme == TPM_ALG_OAEP || scheme == TPM_ALG_NULL) {
+ in_scheme.scheme = TPM_ALG_OAEP;
+ in_scheme.details.oaep.hash_alg = hash_alg;
+ } else {
+ LOG(ERROR) << "Invalid Signing scheme used.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+
+ TPMT_PUBLIC public_area;
+ TPM_RC result = GetKeyPublicArea(key_handle, &public_area);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error finding public area for: " << key_handle;
+ return result;
+ } else if (public_area.type != TPM_ALG_RSA) {
+ LOG(ERROR) << "Key handle given is not an RSA key";
+ return SAPI_RC_BAD_PARAMETER;
+ } else if ((public_area.object_attributes & kDecrypt) == 0) {
+ LOG(ERROR) << "Key handle given is not a decryption key";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ if ((public_area.object_attributes & kRestricted) != 0) {
+ LOG(ERROR) << "Cannot use RSAES for encryption with a restricted key";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ std::string key_name;
+ result = ComputeKeyName(public_area, &key_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error computing key name for: " << key_handle;
+ return result;
+ }
+
+ TPM2B_DATA label;
+ label.size = 0;
+ TPM2B_PUBLIC_KEY_RSA in_message = Make_TPM2B_PUBLIC_KEY_RSA(plaintext);
+ TPM2B_PUBLIC_KEY_RSA out_message;
+ result = factory_.GetTpm()->RSA_EncryptSync(key_handle,
+ key_name,
+ in_message,
+ in_scheme,
+ label,
+ &out_message,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error performing RSA encrypt: "
+ << GetErrorString(result);
+ return result;
+ }
+ ciphertext->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(out_message));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::AsymmetricDecrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& ciphertext,
+ AuthorizationDelegate* delegate,
+ std::string* plaintext) {
+ TPMT_RSA_DECRYPT in_scheme;
+ if (hash_alg == TPM_ALG_NULL) {
+ hash_alg = TPM_ALG_SHA256;
+ }
+ if (scheme == TPM_ALG_RSAES) {
+ in_scheme.scheme = TPM_ALG_RSAES;
+ } else if (scheme == TPM_ALG_OAEP || scheme == TPM_ALG_NULL) {
+ in_scheme.scheme = TPM_ALG_OAEP;
+ in_scheme.details.oaep.hash_alg = hash_alg;
+ } else {
+ LOG(ERROR) << "Invalid Signing scheme used.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPMT_PUBLIC public_area;
+ result = GetKeyPublicArea(key_handle, &public_area);
+ if (result) {
+ LOG(ERROR) << "Error finding public area for: " << key_handle;
+ return result;
+ } else if (public_area.type != TPM_ALG_RSA) {
+ LOG(ERROR) << "Key handle given is not an RSA key";
+ return SAPI_RC_BAD_PARAMETER;
+ } else if ((public_area.object_attributes & kDecrypt) == 0) {
+ LOG(ERROR) << "Key handle given is not a decryption key";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ if ((public_area.object_attributes & kRestricted) != 0) {
+ LOG(ERROR) << "Cannot use RSAES for encryption with a restricted key";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ std::string key_name;
+ result = ComputeKeyName(public_area, &key_name);
+ if (result) {
+ LOG(ERROR) << "Error computing key name for: " << key_handle;
+ return result;
+ }
+
+ TPM2B_DATA label;
+ label.size = 0;
+ TPM2B_PUBLIC_KEY_RSA in_message = Make_TPM2B_PUBLIC_KEY_RSA(ciphertext);
+ TPM2B_PUBLIC_KEY_RSA out_message;
+ result = factory_.GetTpm()->RSA_DecryptSync(key_handle,
+ key_name,
+ in_message,
+ in_scheme,
+ label,
+ &out_message,
+ delegate);
+ if (result) {
+ LOG(ERROR) << "Error performing RSA decrypt: "
+ << GetErrorString(result);
+ return result;
+ }
+ plaintext->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(out_message));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::Sign(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* signature) {
+ TPMT_SIG_SCHEME in_scheme;
+ if (hash_alg == TPM_ALG_NULL) {
+ hash_alg = TPM_ALG_SHA256;
+ }
+ if (scheme == TPM_ALG_RSAPSS) {
+ in_scheme.scheme = TPM_ALG_RSAPSS;
+ in_scheme.details.rsapss.hash_alg = hash_alg;
+ } else if (scheme == TPM_ALG_RSASSA || scheme == TPM_ALG_NULL) {
+ in_scheme.scheme = TPM_ALG_RSASSA;
+ in_scheme.details.rsassa.hash_alg = hash_alg;
+ } else {
+ LOG(ERROR) << "Invalid Signing scheme used.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPMT_PUBLIC public_area;
+ result = GetKeyPublicArea(key_handle, &public_area);
+ if (result) {
+ LOG(ERROR) << "Error finding public area for: " << key_handle;
+ return result;
+ } else if (public_area.type != TPM_ALG_RSA) {
+ LOG(ERROR) << "Key handle given is not an RSA key";
+ return SAPI_RC_BAD_PARAMETER;
+ } else if ((public_area.object_attributes & kSign) == 0) {
+ LOG(ERROR) << "Key handle given is not a signging key";
+ return SAPI_RC_BAD_PARAMETER;
+ } else if ((public_area.object_attributes & kRestricted) != 0) {
+ LOG(ERROR) << "Key handle references a restricted key";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+
+ std::string key_name;
+ result = ComputeKeyName(public_area, &key_name);
+ if (result) {
+ LOG(ERROR) << "Error computing key name for: " << key_handle;
+ return result;
+ }
+ std::string digest = HashString(plaintext, hash_alg);
+ TPM2B_DIGEST tpm_digest = Make_TPM2B_DIGEST(digest);
+ TPMT_SIGNATURE signature_out;
+ TPMT_TK_HASHCHECK validation;
+ validation.tag = TPM_ST_HASHCHECK;
+ validation.hierarchy = TPM_RH_NULL;
+ validation.digest.size = 0;
+ result = factory_.GetTpm()->SignSync(key_handle,
+ key_name,
+ tpm_digest,
+ in_scheme,
+ validation,
+ &signature_out,
+ delegate);
+ if (result) {
+ LOG(ERROR) << "Error signing digest: " << GetErrorString(result);
+ return result;
+ }
+ if (scheme == TPM_ALG_RSAPSS) {
+ signature->resize(signature_out.signature.rsapss.sig.size);
+ signature->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(
+ signature_out.signature.rsapss.sig));
+ } else {
+ signature->resize(signature_out.signature.rsassa.sig.size);
+ signature->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(
+ signature_out.signature.rsassa.sig));
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::Verify(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ const std::string& signature,
+ AuthorizationDelegate* delegate) {
+ TPMT_PUBLIC public_area;
+ TPM_RC return_code = GetKeyPublicArea(key_handle, &public_area);
+ if (return_code) {
+ LOG(ERROR) << "Error finding public area for: " << key_handle;
+ return return_code;
+ } else if (public_area.type != TPM_ALG_RSA) {
+ LOG(ERROR) << "Key handle given is not an RSA key";
+ return SAPI_RC_BAD_PARAMETER;
+ } else if ((public_area.object_attributes & kSign) == 0) {
+ LOG(ERROR) << "Key handle given is not a signing key";
+ return SAPI_RC_BAD_PARAMETER;
+ } else if ((public_area.object_attributes & kRestricted) != 0) {
+ LOG(ERROR) << "Cannot use RSAPSS for signing with a restricted key";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ if (hash_alg == TPM_ALG_NULL) {
+ hash_alg = TPM_ALG_SHA256;
+ }
+
+ TPMT_SIGNATURE signature_in;
+ if (scheme == TPM_ALG_RSAPSS) {
+ signature_in.sig_alg = TPM_ALG_RSAPSS;
+ signature_in.signature.rsapss.hash = hash_alg;
+ signature_in.signature.rsapss.sig = Make_TPM2B_PUBLIC_KEY_RSA(signature);
+ } else if (scheme == TPM_ALG_NULL || scheme == TPM_ALG_RSASSA) {
+ signature_in.sig_alg = TPM_ALG_RSASSA;
+ signature_in.signature.rsassa.hash = hash_alg;
+ signature_in.signature.rsassa.sig = Make_TPM2B_PUBLIC_KEY_RSA(signature);
+ } else {
+ LOG(ERROR) << "Invalid scheme used to verify signature.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ std::string key_name;
+ TPMT_TK_VERIFIED verified;
+ std::string digest = HashString(plaintext, hash_alg);
+ TPM2B_DIGEST tpm_digest = Make_TPM2B_DIGEST(digest);
+ return_code = factory_.GetTpm()->VerifySignatureSync(key_handle,
+ key_name,
+ tpm_digest,
+ signature_in,
+ &verified,
+ delegate);
+ if (return_code == TPM_RC_SIGNATURE) {
+ LOG(WARNING) << "Incorrect signature for given digest.";
+ return TPM_RC_SIGNATURE;
+ } else if (return_code && return_code != TPM_RC_SIGNATURE) {
+ LOG(ERROR) << "Error verifying signature: " << GetErrorString(return_code);
+ return return_code;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::CertifyCreation(TPM_HANDLE key_handle,
+ const std::string& creation_blob) {
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ if (!factory_.GetBlobParser()->ParseCreationBlob(creation_blob,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket)) {
+ LOG(ERROR) << "Error parsing CreationBlob.";
+ return SAPI_RC_BAD_PARAMETER;
+ }
+ TPM2B_DATA qualifying_data;
+ qualifying_data.size = 0;
+ TPMT_SIG_SCHEME in_scheme;
+ in_scheme.scheme = TPM_ALG_NULL;
+ TPM2B_ATTEST certify_info;
+ TPMT_SIGNATURE signature;
+ scoped_ptr<AuthorizationDelegate> delegate =
+ factory_.GetPasswordAuthorization("");
+ TPM_RC result = factory_.GetTpm()->CertifyCreationSync(TPM_RH_NULL,
+ "",
+ key_handle,
+ "",
+ qualifying_data,
+ creation_hash,
+ in_scheme,
+ creation_ticket,
+ &certify_info,
+ &signature,
+ delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error certifying key creation: " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::ChangeKeyAuthorizationData(
+ TPM_HANDLE key_handle,
+ const std::string& new_password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) {
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string key_name;
+ std::string parent_name;
+ result = GetKeyName(key_handle, &key_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting Key name for key_handle: "
+ << GetErrorString(result);
+ return result;
+ }
+ result = GetKeyName(kRSAStorageRootKey, &parent_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting Key name for RSA-SRK: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPM2B_AUTH new_auth = Make_TPM2B_DIGEST(new_password);
+ TPM2B_PRIVATE new_private_data;
+ new_private_data.size = 0;
+ result = factory_.GetTpm()->ObjectChangeAuthSync(key_handle,
+ key_name,
+ kRSAStorageRootKey,
+ parent_name,
+ new_auth,
+ &new_private_data,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error changing object authorization data: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (key_blob) {
+ TPMT_PUBLIC public_data;
+ result = GetKeyPublicArea(key_handle, &public_data);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ if (!factory_.GetBlobParser()->SerializeKeyBlob(
+ Make_TPM2B_PUBLIC(public_data), new_private_data, key_blob)) {
+ return SAPI_RC_BAD_TCTI_STRUCTURE;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::ImportRSAKey(AsymmetricKeyUsage key_type,
+ const std::string& modulus,
+ uint32_t public_exponent,
+ const std::string& prime_factor,
+ const std::string& password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) {
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string parent_name;
+ result = GetKeyName(kRSAStorageRootKey, &parent_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting Key name for RSA-SRK: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
+ public_area.object_attributes = kUserWithAuth | kNoDA;
+ switch (key_type) {
+ case AsymmetricKeyUsage::kDecryptKey:
+ public_area.object_attributes |= kDecrypt;
+ break;
+ case AsymmetricKeyUsage::kSignKey:
+ public_area.object_attributes |= kSign;
+ break;
+ case AsymmetricKeyUsage::kDecryptAndSignKey:
+ public_area.object_attributes |= (kSign | kDecrypt);
+ break;
+ }
+ public_area.parameters.rsa_detail.key_bits = modulus.size() * 8;
+ public_area.parameters.rsa_detail.exponent = public_exponent;
+ public_area.unique.rsa = Make_TPM2B_PUBLIC_KEY_RSA(modulus);
+ TPM2B_DATA encryption_key;
+ encryption_key.size = kAesKeySize;
+ CHECK_EQ(RAND_bytes(encryption_key.buffer, encryption_key.size), 1) <<
+ "Error generating a cryptographically random Aes Key.";
+ TPM2B_PUBLIC public_data = Make_TPM2B_PUBLIC(public_area);
+ TPM2B_ENCRYPTED_SECRET in_sym_seed = Make_TPM2B_ENCRYPTED_SECRET("");
+ TPMT_SYM_DEF_OBJECT symmetric_alg;
+ symmetric_alg.algorithm = TPM_ALG_AES;
+ symmetric_alg.key_bits.aes = kAesKeySize * 8;
+ symmetric_alg.mode.aes = TPM_ALG_CFB;
+ TPMT_SENSITIVE in_sensitive;
+ in_sensitive.sensitive_type = TPM_ALG_RSA;
+ in_sensitive.auth_value = Make_TPM2B_DIGEST(password);
+ in_sensitive.seed_value = Make_TPM2B_DIGEST("");
+ in_sensitive.sensitive.rsa = Make_TPM2B_PRIVATE_KEY_RSA(prime_factor);
+ TPM2B_PRIVATE private_data;
+ result = EncryptPrivateData(in_sensitive, public_area,
+ &private_data, &encryption_key);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating encrypted private struct: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPM2B_PRIVATE tpm_private_data;
+ tpm_private_data.size = 0;
+ result = factory_.GetTpm()->ImportSync(kRSAStorageRootKey,
+ parent_name,
+ encryption_key,
+ public_data,
+ private_data,
+ in_sym_seed,
+ symmetric_alg,
+ &tpm_private_data,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error importing key: " << GetErrorString(result);
+ return result;
+ }
+ if (key_blob) {
+ if (!factory_.GetBlobParser()->SerializeKeyBlob(
+ public_data, tpm_private_data, key_blob)) {
+ return SAPI_RC_BAD_TCTI_STRUCTURE;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::CreateRSAKeyPair(AsymmetricKeyUsage key_type,
+ int modulus_bits,
+ uint32_t public_exponent,
+ const std::string& password,
+ const std::string& policy_digest,
+ bool use_only_policy_authorization,
+ int creation_pcr_index,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob,
+ std::string* creation_blob) {
+ CHECK(key_blob);
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string parent_name;
+ result = GetKeyName(kRSAStorageRootKey, &parent_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting Key name for RSA-SRK: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
+ public_area.auth_policy = Make_TPM2B_DIGEST(policy_digest);
+ public_area.object_attributes |=
+ (kSensitiveDataOrigin | kUserWithAuth | kNoDA);
+ switch (key_type) {
+ case AsymmetricKeyUsage::kDecryptKey:
+ public_area.object_attributes |= kDecrypt;
+ break;
+ case AsymmetricKeyUsage::kSignKey:
+ public_area.object_attributes |= kSign;
+ break;
+ case AsymmetricKeyUsage::kDecryptAndSignKey:
+ public_area.object_attributes |= (kSign | kDecrypt);
+ break;
+ }
+ if (use_only_policy_authorization && !policy_digest.empty()) {
+ public_area.object_attributes |= kAdminWithPolicy;
+ public_area.object_attributes &= (~kUserWithAuth);
+ }
+ public_area.parameters.rsa_detail.key_bits = modulus_bits;
+ public_area.parameters.rsa_detail.exponent = public_exponent;
+ TPML_PCR_SELECTION creation_pcrs = {};
+ if (creation_pcr_index == kNoCreationPCR) {
+ creation_pcrs.count = 0;
+ } else if (creation_pcr_index < 0 ||
+ creation_pcr_index > (PCR_SELECT_MIN * 8)) {
+ LOG(ERROR) << "Creation PCR index is not within the allocated bank.";
+ return SAPI_RC_BAD_PARAMETER;
+ } else {
+ creation_pcrs.count = 1;
+ creation_pcrs.pcr_selections[0].hash = TPM_ALG_SHA256;
+ creation_pcrs.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
+ creation_pcrs.pcr_selections[0].pcr_select[creation_pcr_index / 8] =
+ 1 << (creation_pcr_index % 8);
+ }
+ TPMS_SENSITIVE_CREATE sensitive;
+ sensitive.user_auth = Make_TPM2B_DIGEST(password);
+ sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
+ TPM2B_SENSITIVE_CREATE sensitive_create = Make_TPM2B_SENSITIVE_CREATE(
+ sensitive);
+ TPM2B_DATA outside_info = Make_TPM2B_DATA("");
+ TPM2B_PUBLIC out_public;
+ out_public.size = 0;
+ TPM2B_PRIVATE out_private;
+ out_private.size = 0;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ result = factory_.GetTpm()->CreateSync(kRSAStorageRootKey,
+ parent_name,
+ sensitive_create,
+ Make_TPM2B_PUBLIC(public_area),
+ outside_info,
+ creation_pcrs,
+ &out_private,
+ &out_public,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
+ return result;
+ }
+ if (!factory_.GetBlobParser()->SerializeKeyBlob(
+ out_public, out_private, key_blob)) {
+ return SAPI_RC_BAD_TCTI_STRUCTURE;
+ }
+ if (creation_blob) {
+ if (!factory_.GetBlobParser()->SerializeCreationBlob(
+ creation_data, creation_hash, creation_ticket, creation_blob)) {
+ return SAPI_RC_BAD_TCTI_STRUCTURE;
+ }
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::LoadKey(const std::string& key_blob,
+ AuthorizationDelegate* delegate,
+ TPM_HANDLE* key_handle) {
+ CHECK(key_handle);
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string parent_name;
+ result = GetKeyName(kRSAStorageRootKey, &parent_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting parent key name: " << GetErrorString(result);
+ return result;
+ }
+ TPM2B_PUBLIC in_public;
+ TPM2B_PRIVATE in_private;
+ if (!factory_.GetBlobParser()->ParseKeyBlob(
+ key_blob, &in_public, &in_private)) {
+ return SAPI_RC_BAD_TCTI_STRUCTURE;
+ }
+ TPM2B_NAME key_name;
+ key_name.size = 0;
+ result = factory_.GetTpm()->LoadSync(kRSAStorageRootKey,
+ parent_name,
+ in_private,
+ in_public,
+ key_handle,
+ &key_name,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading key: " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::GetKeyName(TPM_HANDLE handle, std::string* name) {
+ CHECK(name);
+ TPM_RC result;
+ TPMT_PUBLIC public_data;
+ result = GetKeyPublicArea(handle, &public_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error fetching public info: " << GetErrorString(result);
+ return result;
+ }
+ result = ComputeKeyName(public_data, name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error computing key name: " << GetErrorString(result);
+ return TPM_RC_SUCCESS;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::GetKeyPublicArea(TPM_HANDLE handle,
+ TPMT_PUBLIC* public_data) {
+ CHECK(public_data);
+ TPM2B_NAME out_name;
+ TPM2B_PUBLIC public_area;
+ TPM2B_NAME qualified_name;
+ std::string handle_name; // Unused
+ TPM_RC return_code = factory_.GetTpm()->ReadPublicSync(handle,
+ handle_name,
+ &public_area,
+ &out_name,
+ &qualified_name,
+ nullptr);
+ if (return_code) {
+ LOG(ERROR) << "Error getting public area for object: " << handle;
+ return return_code;
+ }
+ *public_data = public_area.public_area;
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::SealData(const std::string& data_to_seal,
+ const std::string& policy_digest,
+ AuthorizationDelegate* delegate,
+ std::string* sealed_data) {
+ CHECK(sealed_data);
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string parent_name;
+ result = GetKeyName(kRSAStorageRootKey, &parent_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting Key name for RSA-SRK: "
+ << GetErrorString(result);
+ return result;
+ }
+ // We seal data to the TPM by creating a KEYEDHASH object with sign and
+ // decrypt attributes disabled.
+ TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_KEYEDHASH);
+ public_area.auth_policy = Make_TPM2B_DIGEST(policy_digest);
+ public_area.object_attributes = kAdminWithPolicy | kNoDA;
+ public_area.unique.keyed_hash.size = 0;
+ TPML_PCR_SELECTION creation_pcrs = {};
+ TPMS_SENSITIVE_CREATE sensitive;
+ sensitive.user_auth = Make_TPM2B_DIGEST("");
+ sensitive.data = Make_TPM2B_SENSITIVE_DATA(data_to_seal);
+ TPM2B_SENSITIVE_CREATE sensitive_create = Make_TPM2B_SENSITIVE_CREATE(
+ sensitive);
+ TPM2B_DATA outside_info = Make_TPM2B_DATA("");
+ TPM2B_PUBLIC out_public;
+ out_public.size = 0;
+ TPM2B_PRIVATE out_private;
+ out_private.size = 0;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ result = factory_.GetTpm()->CreateSync(kRSAStorageRootKey,
+ parent_name,
+ sensitive_create,
+ Make_TPM2B_PUBLIC(public_area),
+ outside_info,
+ creation_pcrs,
+ &out_private,
+ &out_public,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating sealed object: " << GetErrorString(result);
+ return result;
+ }
+ if (!factory_.GetBlobParser()->SerializeKeyBlob(
+ out_public, out_private, sealed_data)) {
+ return SAPI_RC_BAD_TCTI_STRUCTURE;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::UnsealData(const std::string& sealed_data,
+ AuthorizationDelegate* delegate,
+ std::string* unsealed_data) {
+ CHECK(unsealed_data);
+ TPM_RC result;
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPM_HANDLE object_handle;
+ scoped_ptr<AuthorizationDelegate> password_delegate =
+ factory_.GetPasswordAuthorization("");
+ result = LoadKey(sealed_data, password_delegate.get(), &object_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading sealed object: " << GetErrorString(result);
+ return result;
+ }
+ ScopedKeyHandle sealed_object(factory_, object_handle);
+ std::string object_name;
+ result = GetKeyName(sealed_object.get(), &object_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting object name: " << GetErrorString(result);
+ return result;
+ }
+ TPM2B_SENSITIVE_DATA out_data;
+ result = factory_.GetTpm()->UnsealSync(sealed_object.get(), object_name,
+ &out_data, delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
+ return result;
+ }
+ *unsealed_data = StringFrom_TPM2B_SENSITIVE_DATA(out_data);
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::StartSession(HmacSession* session) {
+ TPM_RC result = session->StartUnboundSession(true /* enable_encryption */);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting unbound session: " << GetErrorString(result);
+ return result;
+ }
+ session->SetEntityAuthorizationValue("");
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::GetPolicyDigestForPcrValue(int pcr_index,
+ const std::string& pcr_value,
+ std::string* policy_digest) {
+ CHECK(policy_digest);
+ scoped_ptr<PolicySession> session = factory_.GetTrialSession();
+ TPM_RC result = session->StartUnboundSession(false);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting unbound trial session: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string mutable_pcr_value;
+ if (pcr_value.empty()) {
+ result = ReadPCR(pcr_index, &mutable_pcr_value);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading pcr_value: " << GetErrorString(result);
+ return result;
+ }
+ } else {
+ mutable_pcr_value = pcr_value;
+ }
+ result = session->PolicyPCR(pcr_index, mutable_pcr_value);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy to PCR value: "
+ << GetErrorString(result);
+ return result;
+ }
+ result = session->GetDigest(policy_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::DefineNVSpace(uint32_t index,
+ size_t num_bytes,
+ AuthorizationDelegate* delegate) {
+ TPM_RC result;
+ if (num_bytes > MAX_NV_INDEX_SIZE) {
+ result = SAPI_RC_BAD_SIZE;
+ LOG(ERROR) << "Cannot define non-volatile space of given size: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot define non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ TPMS_NV_PUBLIC public_data;
+ public_data.nv_index = nv_index;
+ public_data.name_alg = TPM_ALG_SHA256;
+ // We define the following attributes for NVSpaces created:
+ // TPMA_NV_NO_DA: Dictionary attack does not trigger on authorization errors.
+ // TPMA_NV_OWNERWRITE: Owner authorization must be provided on write actions.
+ // TPMA_NV_WRITEDEFINE: NVSpace is write lockable, and lock persists across
+ // reboot.
+ // TPMA_NV_AUTHREAD: The index authValue (default: "") can be used to
+ // authorize read actions.
+ public_data.attributes = TPMA_NV_NO_DA |
+ TPMA_NV_OWNERWRITE |
+ TPMA_NV_WRITEDEFINE |
+ TPMA_NV_AUTHREAD;
+ public_data.auth_policy = Make_TPM2B_DIGEST("");
+ public_data.data_size = num_bytes;
+ TPM2B_AUTH authorization = Make_TPM2B_DIGEST("");
+ TPM2B_NV_PUBLIC public_area = Make_TPM2B_NV_PUBLIC(public_data);
+ result = factory_.GetTpm()->NV_DefineSpaceSync(
+ TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ authorization,
+ public_area,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error defining non-volatile space: "
+ << GetErrorString(result);
+ return result;
+ }
+ nvram_public_area_map_[index] = public_data;
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::DestroyNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) {
+ TPM_RC result;
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot undefine non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string nv_name;
+ result = GetNVSpaceName(index, &nv_name);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ result = factory_.GetTpm()->NV_UndefineSpaceSync(
+ TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ nv_index,
+ nv_name,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error undefining non-volatile space: "
+ << GetErrorString(result);
+ return result;
+ }
+ nvram_public_area_map_.erase(index);
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::LockNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) {
+ TPM_RC result;
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot lock non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string nv_name;
+ result = GetNVSpaceName(index, &nv_name);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ result = factory_.GetTpm()->NV_WriteLockSync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ nv_index,
+ nv_name,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error locking non-volatile spaces: "
+ << GetErrorString(result);
+ return result;
+ }
+ auto it = nvram_public_area_map_.find(index);
+ if (it != nvram_public_area_map_.end()) {
+ it->second.attributes |= TPMA_NV_WRITELOCKED;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::WriteNVSpace(uint32_t index,
+ uint32_t offset,
+ const std::string& nvram_data,
+ AuthorizationDelegate* delegate) {
+ TPM_RC result;
+ if (nvram_data.size() > MAX_NV_BUFFER_SIZE) {
+ result = SAPI_RC_BAD_SIZE;
+ LOG(ERROR) << "Insufficient buffer for non-volatile write: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot write to non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string nv_name;
+ result = GetNVSpaceName(index, &nv_name);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ result = factory_.GetTpm()->NV_WriteSync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ nv_index,
+ nv_name,
+ Make_TPM2B_MAX_NV_BUFFER(nvram_data),
+ offset,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error writing to non-volatile space: "
+ << GetErrorString(result);
+ return result;
+ }
+ auto it = nvram_public_area_map_.find(index);
+ if (it != nvram_public_area_map_.end()) {
+ it->second.attributes |= TPMA_NV_WRITTEN;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::ReadNVSpace(uint32_t index,
+ uint32_t offset,
+ size_t num_bytes,
+ std::string* nvram_data,
+ AuthorizationDelegate* delegate) {
+ TPM_RC result;
+ if (num_bytes > MAX_NV_BUFFER_SIZE) {
+ result = SAPI_RC_BAD_SIZE;
+ LOG(ERROR) << "Insufficient buffer for non-volatile read: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot read from non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ if (delegate == nullptr) {
+ result = SAPI_RC_INVALID_SESSIONS;
+ LOG(ERROR) << "This method needs a valid authorization delegate: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string nv_name;
+ result = GetNVSpaceName(index, &nv_name);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ TPM2B_MAX_NV_BUFFER data_buffer;
+ data_buffer.size = 0;
+ result = factory_.GetTpm()->NV_ReadSync(nv_index,
+ nv_name,
+ nv_index,
+ nv_name,
+ num_bytes,
+ offset,
+ &data_buffer,
+ delegate);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading from non-volatile space: "
+ << GetErrorString(result);
+ return result;
+ }
+ nvram_data->assign(StringFrom_TPM2B_MAX_NV_BUFFER(data_buffer));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::GetNVSpaceName(uint32_t index, std::string* name) {
+ TPM_RC result;
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot read from non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ TPMS_NV_PUBLIC nv_public_data;
+ result = GetNVSpacePublicArea(index, &nv_public_data);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ result = ComputeNVSpaceName(nv_public_data, name);
+ if (result != TPM_RC_SUCCESS) {
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::GetNVSpacePublicArea(uint32_t index,
+ TPMS_NV_PUBLIC* public_data) {
+ TPM_RC result;
+ if (index > kMaxNVSpaceIndex) {
+ result = SAPI_RC_BAD_PARAMETER;
+ LOG(ERROR) << "Cannot read from non-volatile space with the given index: "
+ << GetErrorString(result);
+ return result;
+ }
+ auto it = nvram_public_area_map_.find(index);
+ if (it != nvram_public_area_map_.end()) {
+ *public_data = it->second;
+ return TPM_RC_SUCCESS;
+ }
+ TPM2B_NAME nvram_name;
+ TPM2B_NV_PUBLIC public_area;
+ public_area.nv_public.nv_index = 0;
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ result = factory_.GetTpm()->NV_ReadPublicSync(nv_index,
+ "",
+ &public_area,
+ &nvram_name,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading non-volatile space public information: "
+ << GetErrorString(result);
+ return result;
+ }
+ *public_data = public_area.nv_public;
+ nvram_public_area_map_[index] = public_area.nv_public;
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::SetKnownOwnerPassword(
+ const std::string& known_owner_password) {
+ scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
+ TPM_RC result = tpm_state->Initialize();
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ scoped_ptr<AuthorizationDelegate> delegate =
+ factory_.GetPasswordAuthorization("");
+ if (tpm_state->IsOwnerPasswordSet()) {
+ LOG(INFO) << "Owner password is already set. "
+ << "This is normal if ownership is already taken.";
+ return TPM_RC_SUCCESS;
+ }
+ result = SetHierarchyAuthorization(TPM_RH_OWNER,
+ known_owner_password,
+ delegate.get());
+ if (result) {
+ LOG(ERROR) << "Error setting storage hierarchy authorization "
+ << "to its default value: " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::CreateStorageRootKeys(
+ const std::string& owner_password) {
+ TPM_RC result = TPM_RC_SUCCESS;
+ scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
+ result = tpm_state->Initialize();
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ Tpm* tpm = factory_.GetTpm();
+ TPMT_PUBLIC public_area;
+ TPML_PCR_SELECTION creation_pcrs;
+ creation_pcrs.count = 0;
+ TPMS_SENSITIVE_CREATE sensitive;
+ sensitive.user_auth = Make_TPM2B_DIGEST("");
+ sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
+ TPM_HANDLE object_handle;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_digest;
+ TPMT_TK_CREATION creation_ticket;
+ TPM2B_NAME object_name;
+ object_name.size = 0;
+ scoped_ptr<AuthorizationDelegate> delegate =
+ factory_.GetPasswordAuthorization(owner_password);
+ if ((tpm_state->IsRSASupported()) &&
+ (GetKeyPublicArea(kRSAStorageRootKey, &public_area) != TPM_RC_SUCCESS)) {
+ public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
+ public_area.object_attributes |=
+ (kSensitiveDataOrigin | kUserWithAuth | kNoDA |
+ kRestricted | kDecrypt);
+ public_area.parameters.rsa_detail.symmetric.algorithm = TPM_ALG_AES;
+ public_area.parameters.rsa_detail.symmetric.key_bits.aes = 128;
+ public_area.parameters.rsa_detail.symmetric.mode.aes = TPM_ALG_CFB;
+ TPM2B_PUBLIC rsa_public_area = Make_TPM2B_PUBLIC(public_area);
+ result = tpm->CreatePrimarySync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ Make_TPM2B_SENSITIVE_CREATE(sensitive),
+ rsa_public_area,
+ Make_TPM2B_DATA(""),
+ creation_pcrs,
+ &object_handle,
+ &rsa_public_area,
+ &creation_data,
+ &creation_digest,
+ &creation_ticket,
+ &object_name,
+ delegate.get());
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ ScopedKeyHandle rsa_key(factory_, object_handle);
+ // This will make the key persistent.
+ result = tpm->EvictControlSync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ object_handle,
+ StringFrom_TPM2B_NAME(object_name),
+ kRSAStorageRootKey,
+ delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ } else {
+ LOG(INFO) << "Not creating RSA SRK because it isnt supported or it exists.";
+ }
+
+ // Do it again for ECC.
+ if ((tpm_state->IsECCSupported()) &&
+ (GetKeyPublicArea(kECCStorageRootKey, &public_area) != TPM_RC_SUCCESS)) {
+ public_area = CreateDefaultPublicArea(TPM_ALG_ECC);
+ public_area.object_attributes |=
+ (kSensitiveDataOrigin | kUserWithAuth | kNoDA |
+ kRestricted | kDecrypt);
+ public_area.parameters.ecc_detail.symmetric.algorithm = TPM_ALG_AES;
+ public_area.parameters.ecc_detail.symmetric.key_bits.aes = 128;
+ public_area.parameters.ecc_detail.symmetric.mode.aes = TPM_ALG_CFB;
+ TPM2B_PUBLIC ecc_public_area = Make_TPM2B_PUBLIC(public_area);
+ result = tpm->CreatePrimarySync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ Make_TPM2B_SENSITIVE_CREATE(sensitive),
+ ecc_public_area,
+ Make_TPM2B_DATA(""),
+ creation_pcrs,
+ &object_handle,
+ &ecc_public_area,
+ &creation_data,
+ &creation_digest,
+ &creation_ticket,
+ &object_name,
+ delegate.get());
+ if (result) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ ScopedKeyHandle ecc_key(factory_, object_handle);
+ // This will make the key persistent.
+ result = tpm->EvictControlSync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ object_handle,
+ StringFrom_TPM2B_NAME(object_name),
+ kECCStorageRootKey,
+ delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ } else {
+ LOG(INFO) << "Not creating ECC SRK because it isnt supported or it exists.";
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::CreateSaltingKey(const std::string& owner_password) {
+ TPMT_PUBLIC public_area;
+ TPM_RC result = GetKeyPublicArea(kSaltingKey, &public_area);
+ if (result == TPM_RC_SUCCESS) {
+ LOG(INFO) << "Salting key already exists.";
+ return result;
+ }
+ std::string parent_name;
+ result = GetKeyName(kRSAStorageRootKey, &parent_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting Key name for RSA-SRK: "
+ << GetErrorString(result);
+ return result;
+ }
+ public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
+ public_area.name_alg = TPM_ALG_SHA256;
+ public_area.object_attributes |=
+ kSensitiveDataOrigin | kUserWithAuth | kNoDA | kDecrypt;
+ TPML_PCR_SELECTION creation_pcrs;
+ creation_pcrs.count = 0;
+ TPMS_SENSITIVE_CREATE sensitive;
+ sensitive.user_auth = Make_TPM2B_DIGEST("");
+ sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
+ TPM2B_SENSITIVE_CREATE sensitive_create = Make_TPM2B_SENSITIVE_CREATE(
+ sensitive);
+ TPM2B_DATA outside_info = Make_TPM2B_DATA("");
+
+ TPM2B_PRIVATE out_private;
+ out_private.size = 0;
+ TPM2B_PUBLIC out_public;
+ out_public.size = 0;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ // TODO(usanghi): MITM vulnerability with SaltingKey creation.
+ // Currently we cannot verify the key returned by the TPM.
+ // crbug.com/442331
+ scoped_ptr<AuthorizationDelegate> delegate =
+ factory_.GetPasswordAuthorization("");
+ result = factory_.GetTpm()->CreateSync(kRSAStorageRootKey,
+ parent_name,
+ sensitive_create,
+ Make_TPM2B_PUBLIC(public_area),
+ outside_info,
+ creation_pcrs,
+ &out_private,
+ &out_public,
+ &creation_data,
+ &creation_hash,
+ &creation_ticket,
+ delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating salting key: " << GetErrorString(result);
+ return result;
+ }
+ TPM2B_NAME key_name;
+ key_name.size = 0;
+ TPM_HANDLE key_handle;
+ result = factory_.GetTpm()->LoadSync(kRSAStorageRootKey,
+ parent_name,
+ out_private,
+ out_public,
+ &key_handle,
+ &key_name,
+ delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading salting key: " << GetErrorString(result);
+ return result;
+ }
+ ScopedKeyHandle key(factory_, key_handle);
+ scoped_ptr<AuthorizationDelegate> owner_delegate =
+ factory_.GetPasswordAuthorization(owner_password);
+ result = factory_.GetTpm()->EvictControlSync(TPM_RH_OWNER,
+ NameFromHandle(TPM_RH_OWNER),
+ key_handle,
+ StringFrom_TPM2B_NAME(key_name),
+ kSaltingKey,
+ owner_delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << __func__ << ": " << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+TPMT_PUBLIC TpmUtilityImpl::CreateDefaultPublicArea(TPM_ALG_ID key_alg) {
+ TPMT_PUBLIC public_area;
+ public_area.name_alg = TPM_ALG_SHA256;
+ public_area.auth_policy = Make_TPM2B_DIGEST("");
+ public_area.object_attributes = kFixedTPM | kFixedParent;
+ if (key_alg == TPM_ALG_RSA) {
+ public_area.type = TPM_ALG_RSA;
+ public_area.parameters.rsa_detail.scheme.scheme = TPM_ALG_NULL;
+ public_area.parameters.rsa_detail.symmetric.algorithm = TPM_ALG_NULL;
+ public_area.parameters.rsa_detail.key_bits = 2048;
+ public_area.parameters.rsa_detail.exponent = 0;
+ public_area.unique.rsa = Make_TPM2B_PUBLIC_KEY_RSA("");
+ } else if (key_alg == TPM_ALG_ECC) {
+ public_area.type = TPM_ALG_ECC;
+ public_area.parameters.ecc_detail.curve_id = TPM_ECC_NIST_P256;
+ public_area.parameters.ecc_detail.kdf.scheme = TPM_ALG_NULL;
+ public_area.unique.ecc.x = Make_TPM2B_ECC_PARAMETER("");
+ public_area.unique.ecc.y = Make_TPM2B_ECC_PARAMETER("");
+ } else if (key_alg == TPM_ALG_KEYEDHASH) {
+ public_area.type = TPM_ALG_KEYEDHASH;
+ public_area.parameters.keyed_hash_detail.scheme.scheme = TPM_ALG_NULL;
+ } else {
+ LOG(WARNING) << "Unrecognized key_type. Not filling parameters.";
+ }
+ return public_area;
+}
+
+TPM_RC TpmUtilityImpl::SetHierarchyAuthorization(
+ TPMI_RH_HIERARCHY_AUTH hierarchy,
+ const std::string& password,
+ AuthorizationDelegate* authorization) {
+ if (password.size() > kMaxPasswordLength) {
+ LOG(ERROR) << "Hierarchy passwords can be at most " << kMaxPasswordLength
+ << " bytes. Current password length is: " << password.size();
+ return SAPI_RC_BAD_SIZE;
+ }
+ return factory_.GetTpm()->HierarchyChangeAuthSync(
+ hierarchy,
+ NameFromHandle(hierarchy),
+ Make_TPM2B_DIGEST(password),
+ authorization);
+}
+
+TPM_RC TpmUtilityImpl::DisablePlatformHierarchy(
+ AuthorizationDelegate* authorization) {
+ return factory_.GetTpm()->HierarchyControlSync(
+ TPM_RH_PLATFORM, // The authorizing entity.
+ NameFromHandle(TPM_RH_PLATFORM),
+ TPM_RH_PLATFORM, // The target hierarchy.
+ 0, // Disable.
+ authorization);
+}
+
+TPM_RC TpmUtilityImpl::ComputeKeyName(const TPMT_PUBLIC& public_area,
+ std::string* object_name) {
+ CHECK(object_name);
+ if (public_area.type == TPM_ALG_ERROR) {
+ // We do not compute a name for empty public area.
+ object_name->clear();
+ return TPM_RC_SUCCESS;
+ }
+ std::string serialized_public_area;
+ TPM_RC result = Serialize_TPMT_PUBLIC(public_area, &serialized_public_area);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
+ return result;
+ }
+ std::string serialized_name_alg;
+ result = Serialize_TPM_ALG_ID(TPM_ALG_SHA256, &serialized_name_alg);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
+ return result;
+ }
+ object_name->assign(serialized_name_alg +
+ crypto::SHA256HashString(serialized_public_area));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::ComputeNVSpaceName(const TPMS_NV_PUBLIC& nv_public_area,
+ std::string* nv_name) {
+ CHECK(nv_name);
+ if ((nv_public_area.nv_index & NV_INDEX_FIRST) == 0) {
+ // If the index is not an nvram index, we do not compute a name.
+ nv_name->clear();
+ return TPM_RC_SUCCESS;
+ }
+ std::string serialized_public_area;
+ TPM_RC result = Serialize_TPMS_NV_PUBLIC(nv_public_area,
+ &serialized_public_area);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
+ return result;
+ }
+ std::string serialized_name_alg;
+ result = Serialize_TPM_ALG_ID(TPM_ALG_SHA256, &serialized_name_alg);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
+ return result;
+ }
+ nv_name->assign(serialized_name_alg +
+ crypto::SHA256HashString(serialized_public_area));
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TpmUtilityImpl::EncryptPrivateData(const TPMT_SENSITIVE& sensitive_area,
+ const TPMT_PUBLIC& public_area,
+ TPM2B_PRIVATE* encrypted_private_data,
+ TPM2B_DATA* encryption_key) {
+ TPM2B_SENSITIVE sensitive_data = Make_TPM2B_SENSITIVE(sensitive_area);
+ std::string serialized_sensitive_data;
+ TPM_RC result = Serialize_TPM2B_SENSITIVE(sensitive_data,
+ &serialized_sensitive_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing sensitive data: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string object_name;
+ result = ComputeKeyName(public_area, &object_name);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error computing object name: " << GetErrorString(result);
+ return result;
+ }
+ TPM2B_DIGEST inner_integrity = Make_TPM2B_DIGEST(crypto::SHA256HashString(
+ serialized_sensitive_data + object_name));
+ std::string serialized_inner_integrity;
+ result = Serialize_TPM2B_DIGEST(inner_integrity, &serialized_inner_integrity);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error serializing inner integrity: "
+ << GetErrorString(result);
+ return result;
+ }
+ std::string unencrypted_private_data = serialized_inner_integrity +
+ serialized_sensitive_data;
+ AES_KEY key;
+ AES_set_encrypt_key(encryption_key->buffer, kAesKeySize * 8, &key);
+ std::string private_data_string(unencrypted_private_data.size(), 0);
+ int iv_in = 0;
+ unsigned char iv[MAX_AES_BLOCK_SIZE_BYTES] = {0};
+ AES_cfb128_encrypt(
+ reinterpret_cast<const unsigned char*>(unencrypted_private_data.data()),
+ reinterpret_cast<unsigned char*>(string_as_array(&private_data_string)),
+ unencrypted_private_data.size(), &key, iv, &iv_in, AES_ENCRYPT);
+ *encrypted_private_data = Make_TPM2B_PRIVATE(private_data_string);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error making private area: "
+ << GetErrorString(result);
+ return result;
+ }
+ return TPM_RC_SUCCESS;
+}
+
+} // namespace trunks
diff --git a/trunks/tpm_utility_impl.h b/trunks/tpm_utility_impl.h
new file mode 100644
index 0000000..8d91fc5
--- /dev/null
+++ b/trunks/tpm_utility_impl.h
@@ -0,0 +1,202 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TPM_UTILITY_IMPL_H_
+#define TRUNKS_TPM_UTILITY_IMPL_H_
+
+#include "trunks/tpm_utility.h"
+
+#include <map>
+#include <string>
+
+#include <base/macros.h>
+#include <base/memory/scoped_ptr.h>
+#include <gtest/gtest_prod.h>
+
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class AuthorizationDelegate;
+class TrunksFactory;
+
+// A default implementation of TpmUtility.
+class TRUNKS_EXPORT TpmUtilityImpl : public TpmUtility {
+ public:
+ explicit TpmUtilityImpl(const TrunksFactory& factory);
+ ~TpmUtilityImpl() override;
+
+ // TpmUtility methods.
+ TPM_RC Startup() override;
+ TPM_RC Clear() override;
+ void Shutdown() override;
+ TPM_RC InitializeTpm() override;
+ TPM_RC AllocatePCR(const std::string& platform_password) override;
+ TPM_RC TakeOwnership(const std::string& owner_password,
+ const std::string& endorsement_password,
+ const std::string& lockout_password) override;
+ TPM_RC StirRandom(const std::string& entropy_data,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC GenerateRandom(size_t num_bytes,
+ AuthorizationDelegate* delegate,
+ std::string* random_data) override;
+ TPM_RC ExtendPCR(int pcr_index,
+ const std::string& extend_data,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC ReadPCR(int pcr_index, std::string* pcr_value) override;
+ TPM_RC AsymmetricEncrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* ciphertext) override;
+ TPM_RC AsymmetricDecrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& ciphertext,
+ AuthorizationDelegate* delegate,
+ std::string* plaintext) override;
+ TPM_RC Sign(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* signature) override;
+ TPM_RC Verify(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ const std::string& signature,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC CertifyCreation(TPM_HANDLE key_handle,
+ const std::string& creation_blob) override;
+ TPM_RC ChangeKeyAuthorizationData(TPM_HANDLE key_handle,
+ const std::string& new_password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) override;
+ TPM_RC ImportRSAKey(AsymmetricKeyUsage key_type,
+ const std::string& modulus,
+ uint32_t public_exponent,
+ const std::string& prime_factor,
+ const std::string& password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) override;
+ TPM_RC CreateRSAKeyPair(AsymmetricKeyUsage key_type,
+ int modulus_bits,
+ uint32_t public_exponent,
+ const std::string& password,
+ const std::string& policy_digest,
+ bool use_only_policy_authorization,
+ int creation_pcr_index,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob,
+ std::string* creation_blob) override;
+ TPM_RC LoadKey(const std::string& key_blob,
+ AuthorizationDelegate* delegate,
+ TPM_HANDLE* key_handle) override;
+ TPM_RC GetKeyName(TPM_HANDLE handle, std::string* name) override;
+ TPM_RC GetKeyPublicArea(TPM_HANDLE handle,
+ TPMT_PUBLIC* public_data) override;
+ TPM_RC SealData(const std::string& data_to_seal,
+ const std::string& policy_digest,
+ AuthorizationDelegate* delegate,
+ std::string* sealed_data) override;
+ TPM_RC UnsealData(const std::string& sealed_data,
+ AuthorizationDelegate* delegate,
+ std::string* unsealed_data) override;
+ TPM_RC StartSession(HmacSession* session) override;
+ TPM_RC GetPolicyDigestForPcrValue(int pcr_index,
+ const std::string& pcr_value,
+ std::string* policy_digest) override;
+ TPM_RC DefineNVSpace(uint32_t index,
+ size_t num_bytes,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC DestroyNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC LockNVSpace(uint32_t index, AuthorizationDelegate* delegate) override;
+ TPM_RC WriteNVSpace(uint32_t index,
+ uint32_t offset,
+ const std::string& nvram_data,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC ReadNVSpace(uint32_t index,
+ uint32_t offset,
+ size_t num_bytes,
+ std::string* nvram_data,
+ AuthorizationDelegate* delegate) override;
+ TPM_RC GetNVSpaceName(uint32_t index, std::string* name) override;
+ TPM_RC GetNVSpacePublicArea(uint32_t index,
+ TPMS_NV_PUBLIC* public_data) override;
+
+ private:
+ friend class TpmUtilityTest;
+
+ const TrunksFactory& factory_;
+ std::map<uint32_t, TPMS_NV_PUBLIC> nvram_public_area_map_;
+
+ // This method sets a known owner password in the TPM_RH_OWNER hierarchy.
+ TPM_RC SetKnownOwnerPassword(const std::string& known_owner_password);
+
+ // Synchronously derives storage root keys for RSA and ECC and persists the
+ // keys in the TPM. This operation must be authorized by the |owner_password|
+ // and, on success, KRSAStorageRootKey and kECCStorageRootKey can be used
+ // with an empty authorization value until the TPM is cleared.
+ TPM_RC CreateStorageRootKeys(const std::string& owner_password);
+
+ // This method creates an RSA decryption key to be used for salting sessions.
+ // This method also makes the salting key permanent under the storage
+ // hierarchy.
+ TPM_RC CreateSaltingKey(const std::string& owner_password);
+
+ // This method returns a partially filled TPMT_PUBLIC strucutre,
+ // which can then be modified by other methods to create the public
+ // template for a key. It takes a valid |key_type| tp construct the
+ // parameters.
+ TPMT_PUBLIC CreateDefaultPublicArea(TPM_ALG_ID key_alg);
+
+ // Sets TPM |hierarchy| authorization to |password| using |authorization|.
+ TPM_RC SetHierarchyAuthorization(TPMI_RH_HIERARCHY_AUTH hierarchy,
+ const std::string& password,
+ AuthorizationDelegate* authorization);
+
+ // Disables the TPM platform hierarchy until the next startup. This requires
+ // platform |authorization|.
+ TPM_RC DisablePlatformHierarchy(AuthorizationDelegate* authorization);
+
+ // Given a public area, this method computes the object name. Following
+ // TPM2.0 Specification Part 1 section 16,
+ // object_name = HashAlg || Hash(public_area);
+ TPM_RC ComputeKeyName(const TPMT_PUBLIC& public_area,
+ std::string* object_name);
+
+ // Given a public area, this method computers the NVSpace's name.
+ // It follows TPM2.0 Specification Part 1 section 16,
+ // nv_name = HashAlg || Hash(nv_public_area);
+ TPM_RC ComputeNVSpaceName(const TPMS_NV_PUBLIC& nv_public_area,
+ std::string* nv_name);
+
+ // This encrypts the |sensitive_data| struct according to the specification
+ // defined in TPM2.0 spec Part 1: Figure 19.
+ TPM_RC EncryptPrivateData(const TPMT_SENSITIVE& sensitive_area,
+ const TPMT_PUBLIC& public_area,
+ TPM2B_PRIVATE* encrypted_private_data,
+ TPM2B_DATA* encryption_key);
+
+ DISALLOW_COPY_AND_ASSIGN(TpmUtilityImpl);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TPM_UTILITY_IMPL_H_
diff --git a/trunks/tpm_utility_test.cc b/trunks/tpm_utility_test.cc
new file mode 100644
index 0000000..344b37c
--- /dev/null
+++ b/trunks/tpm_utility_test.cc
@@ -0,0 +1,2004 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include <base/stl_util.h>
+#include <crypto/sha2.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <openssl/aes.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/hmac_authorization_delegate.h"
+#include "trunks/mock_authorization_delegate.h"
+#include "trunks/mock_blob_parser.h"
+#include "trunks/mock_hmac_session.h"
+#include "trunks/mock_policy_session.h"
+#include "trunks/mock_tpm.h"
+#include "trunks/mock_tpm_state.h"
+#include "trunks/tpm_constants.h"
+#include "trunks/tpm_utility_impl.h"
+#include "trunks/trunks_factory_for_test.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::NiceMock;
+using testing::Return;
+using testing::SaveArg;
+using testing::SetArgPointee;
+
+namespace trunks {
+
+// A test fixture for TpmUtility tests.
+class TpmUtilityTest : public testing::Test {
+ public:
+ TpmUtilityTest() : utility_(factory_) {}
+ ~TpmUtilityTest() override {}
+ void SetUp() override {
+ factory_.set_blob_parser(&mock_blob_parser_);
+ factory_.set_tpm_state(&mock_tpm_state_);
+ factory_.set_tpm(&mock_tpm_);
+ factory_.set_hmac_session(&mock_hmac_session_);
+ factory_.set_policy_session(&mock_policy_session_);
+ }
+
+ TPM_RC ComputeKeyName(const TPMT_PUBLIC& public_area,
+ std::string* object_name) {
+ return utility_.ComputeKeyName(public_area, object_name);
+ }
+
+ void SetNVRAMMap(uint32_t index,
+ const TPMS_NV_PUBLIC& public_area) {
+ utility_.nvram_public_area_map_[index] = public_area;
+ }
+
+ TPM_RC GetNVRAMMap(uint32_t index,
+ TPMS_NV_PUBLIC* public_area) {
+ auto it = utility_.nvram_public_area_map_.find(index);
+ if (it == utility_.nvram_public_area_map_.end()) {
+ return TPM_RC_FAILURE;
+ }
+ *public_area = it->second;
+ return TPM_RC_SUCCESS;
+ }
+
+ TPM_RC SetKnownOwnerPassword(const std::string& owner_password) {
+ return utility_.SetKnownOwnerPassword(owner_password);
+ }
+
+ TPM_RC CreateStorageRootKeys(const std::string& owner_password) {
+ return utility_.CreateStorageRootKeys(owner_password);
+ }
+
+ TPM_RC CreateSaltingKey(const std::string& owner_password) {
+ return utility_.CreateSaltingKey(owner_password);
+ }
+
+ protected:
+ TrunksFactoryForTest factory_;
+ NiceMock<MockBlobParser> mock_blob_parser_;
+ NiceMock<MockTpmState> mock_tpm_state_;
+ NiceMock<MockTpm> mock_tpm_;
+ NiceMock<MockAuthorizationDelegate> mock_authorization_delegate_;
+ NiceMock<MockHmacSession> mock_hmac_session_;
+ NiceMock<MockPolicySession> mock_policy_session_;
+ TpmUtilityImpl utility_;
+};
+
+TEST_F(TpmUtilityTest, StartupSuccess) {
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Startup());
+}
+
+TEST_F(TpmUtilityTest, StartupAlreadyStarted) {
+ EXPECT_CALL(mock_tpm_, StartupSync(_, _))
+ .WillRepeatedly(Return(TPM_RC_INITIALIZE));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Startup());
+}
+
+TEST_F(TpmUtilityTest, StartupFailure) {
+ EXPECT_CALL(mock_tpm_, StartupSync(_, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Startup());
+}
+
+TEST_F(TpmUtilityTest, StartupSelfTestFailure) {
+ EXPECT_CALL(mock_tpm_, SelfTestSync(_, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Startup());
+}
+
+TEST_F(TpmUtilityTest, ClearSuccess) {
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Clear());
+}
+
+TEST_F(TpmUtilityTest, ClearAfterBadInit) {
+ EXPECT_CALL(mock_tpm_, ClearSync(_, _, _))
+ .WillOnce(Return(TPM_RC_AUTH_MISSING))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Clear());
+}
+
+TEST_F(TpmUtilityTest, ClearFail) {
+ EXPECT_CALL(mock_tpm_, ClearSync(_, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Clear());
+}
+
+TEST_F(TpmUtilityTest, ShutdownTest) {
+ EXPECT_CALL(mock_tpm_, ShutdownSync(TPM_SU_CLEAR, _));
+ utility_.Shutdown();
+}
+
+TEST_F(TpmUtilityTest, InitializeTpmAlreadyInit) {
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.InitializeTpm());
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.InitializeTpm());
+}
+
+TEST_F(TpmUtilityTest, InitializeTpmSuccess) {
+ EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(YES),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.InitializeTpm());
+}
+
+TEST_F(TpmUtilityTest, InitializeTpmBadAuth) {
+ // Reject attempts to set platform auth.
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_PLATFORM, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.InitializeTpm());
+}
+
+TEST_F(TpmUtilityTest, InitializeTpmDisablePHFails) {
+ EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(YES),
+ Return(TPM_RC_SUCCESS)));
+ // Reject attempts to disable the platform hierarchy.
+ EXPECT_CALL(mock_tpm_, HierarchyControlSync(_, _, TPM_RH_PLATFORM, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.InitializeTpm());
+}
+
+TEST_F(TpmUtilityTest, AllocatePCRSuccess) {
+ TPML_PCR_SELECTION pcr_allocation;
+ EXPECT_CALL(mock_tpm_, PCR_AllocateSync(TPM_RH_PLATFORM, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<2>(&pcr_allocation),
+ SetArgPointee<3>(YES),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AllocatePCR(""));
+ EXPECT_EQ(1, pcr_allocation.count);
+ EXPECT_EQ(TPM_ALG_SHA256, pcr_allocation.pcr_selections[0].hash);
+ EXPECT_EQ(PCR_SELECT_MIN, pcr_allocation.pcr_selections[0].sizeof_select);
+ EXPECT_EQ(0xFF, pcr_allocation.pcr_selections[0].pcr_select[0]);
+ EXPECT_EQ(0xFF, pcr_allocation.pcr_selections[0].pcr_select[1]);
+}
+
+TEST_F(TpmUtilityTest, AllocatePCRCommandFailure) {
+ EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.AllocatePCR(""));
+}
+
+TEST_F(TpmUtilityTest, AllocatePCRTpmFailure) {
+ EXPECT_CALL(mock_tpm_, PCR_AllocateSync(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(NO),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.AllocatePCR(""));
+}
+
+TEST_F(TpmUtilityTest, TakeOwnershipSuccess) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsEndorsementPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsLockoutPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, TakeOwnershipOwnershipDone) {
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, TakeOwnershipBadSession) {
+ EXPECT_CALL(mock_hmac_session_, StartUnboundSession(true))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, TakeOwnershipFailure) {
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_OWNER, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, ChangeOwnerPasswordEndorsementDone) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsLockoutPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, ChangeOwnerPasswordLockoutDone) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsEndorsementPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, ChangeOwnerPasswordEndorsementLockoutDone) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, ChangeOwnerPasswordEndorsementFail) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsEndorsementPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(_, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_ENDORSEMENT, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, ChangeOwnerPasswordLockoutFailure) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsEndorsementPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_state_, IsLockoutPasswordSet())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(_, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_LOCKOUT, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.TakeOwnership("owner",
+ "endorsement",
+ "lockout"));
+}
+
+TEST_F(TpmUtilityTest, StirRandomSuccess) {
+ std::string entropy_data("large test data", 100);
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.StirRandom(entropy_data, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, StirRandomFails) {
+ std::string entropy_data("test data");
+ EXPECT_CALL(mock_tpm_, StirRandomSync(_, nullptr))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.StirRandom(entropy_data, nullptr));
+}
+
+TEST_F(TpmUtilityTest, GenerateRandomSuccess) {
+ // This number is larger than the max bytes the GetRandom call can return.
+ // Therefore we expect software to make multiple calls to fill this many
+ // bytes.
+ int num_bytes = 72;
+ std::string random_data;
+ TPM2B_DIGEST large_random;
+ large_random.size = 32;
+ TPM2B_DIGEST small_random;
+ small_random.size = 8;
+ EXPECT_CALL(mock_tpm_, GetRandomSync(_, _, &mock_authorization_delegate_))
+ .Times(2)
+ .WillRepeatedly(DoAll(SetArgPointee<1>(large_random),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, GetRandomSync(8, _, &mock_authorization_delegate_))
+ .WillOnce(DoAll(SetArgPointee<1>(small_random),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.GenerateRandom(
+ num_bytes, &mock_authorization_delegate_, &random_data));
+ EXPECT_EQ(num_bytes, random_data.size());
+}
+
+TEST_F(TpmUtilityTest, GenerateRandomFails) {
+ int num_bytes = 5;
+ std::string random_data;
+ EXPECT_CALL(mock_tpm_, GetRandomSync(_, _, nullptr))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.GenerateRandom(num_bytes, nullptr, &random_data));
+}
+
+TEST_F(TpmUtilityTest, ExtendPCRSuccess) {
+ TPM_HANDLE pcr_handle = HR_PCR + 1;
+ TPML_DIGEST_VALUES digests;
+ EXPECT_CALL(mock_tpm_,
+ PCR_ExtendSync(pcr_handle, _, _, &mock_authorization_delegate_))
+ .WillOnce(DoAll(SaveArg<2>(&digests),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ExtendPCR(1, "test digest",
+ &mock_authorization_delegate_));
+ EXPECT_EQ(1, digests.count);
+ EXPECT_EQ(TPM_ALG_SHA256, digests.digests[0].hash_alg);
+ std::string hash_string = crypto::SHA256HashString("test digest");
+ EXPECT_EQ(0, memcmp(hash_string.data(),
+ digests.digests[0].digest.sha256,
+ crypto::kSHA256Length));
+}
+
+TEST_F(TpmUtilityTest, ExtendPCRFail) {
+ int pcr_index = 0;
+ TPM_HANDLE pcr_handle = HR_PCR + pcr_index;
+ EXPECT_CALL(mock_tpm_, PCR_ExtendSync(pcr_handle, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.ExtendPCR(pcr_index, "test digest", nullptr));
+}
+
+TEST_F(TpmUtilityTest, ExtendPCRBadParam) {
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ExtendPCR(-1, "test digest", nullptr));
+}
+
+TEST_F(TpmUtilityTest, ReadPCRSuccess) {
+ // The |pcr_index| is chosen to match the structure for |pcr_select|.
+ // If you change |pcr_index|, remember to change |pcr_select|.
+ int pcr_index = 1;
+ std::string pcr_value;
+ TPML_PCR_SELECTION pcr_select;
+ pcr_select.count = 1;
+ pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
+ pcr_select.pcr_selections[0].sizeof_select = 1;
+ pcr_select.pcr_selections[0].pcr_select[0] = 2;
+ TPML_DIGEST pcr_values;
+ pcr_values.count = 1;
+ pcr_values.digests[0].size = 5;
+ EXPECT_CALL(mock_tpm_, PCR_ReadSync(_, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<2>(pcr_select),
+ SetArgPointee<3>(pcr_values),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ReadPCR(pcr_index, &pcr_value));
+}
+
+TEST_F(TpmUtilityTest, ReadPCRFail) {
+ std::string pcr_value;
+ EXPECT_CALL(mock_tpm_, PCR_ReadSync(_, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ReadPCR(1, &pcr_value));
+}
+
+TEST_F(TpmUtilityTest, ReadPCRBadReturn) {
+ std::string pcr_value;
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ReadPCR(1, &pcr_value));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricEncryptSuccess) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string output_ciphertext("ciphertext");
+ std::string ciphertext;
+ TPM2B_PUBLIC_KEY_RSA out_message = Make_TPM2B_PUBLIC_KEY_RSA(
+ output_ciphertext);
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_EncryptSync(key_handle, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SetArgPointee<5>(out_message),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AsymmetricEncrypt(
+ key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ plaintext,
+ &mock_authorization_delegate_,
+ &ciphertext));
+ EXPECT_EQ(0, ciphertext.compare(output_ciphertext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricEncryptFail) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string ciphertext;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_EncryptSync(key_handle, _, _, _, _, _, nullptr))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.AsymmetricEncrypt(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ plaintext,
+ nullptr,
+ &ciphertext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricEncryptBadParams) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string ciphertext;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt | kRestricted;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, nullptr))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.AsymmetricEncrypt(key_handle,
+ TPM_ALG_RSAES,
+ TPM_ALG_NULL,
+ plaintext,
+ nullptr,
+ &ciphertext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricEncryptNullSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string output_ciphertext("ciphertext");
+ std::string ciphertext;
+ TPM2B_PUBLIC_KEY_RSA out_message = Make_TPM2B_PUBLIC_KEY_RSA(
+ output_ciphertext);
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ TPMT_RSA_DECRYPT scheme;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_EncryptSync(key_handle, _, _, _, _, _, nullptr))
+ .WillOnce(DoAll(SetArgPointee<5>(out_message),
+ SaveArg<3>(&scheme),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AsymmetricEncrypt(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ plaintext,
+ nullptr,
+ &ciphertext));
+ EXPECT_EQ(scheme.scheme, TPM_ALG_OAEP);
+ EXPECT_EQ(scheme.details.oaep.hash_alg, TPM_ALG_SHA256);
+}
+
+TEST_F(TpmUtilityTest, AsymmetricEncryptSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string output_ciphertext("ciphertext");
+ std::string ciphertext;
+ TPM2B_PUBLIC_KEY_RSA out_message = Make_TPM2B_PUBLIC_KEY_RSA(
+ output_ciphertext);
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ TPMT_RSA_DECRYPT scheme;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_EncryptSync(key_handle, _, _, _, _, _, nullptr))
+ .WillOnce(DoAll(SetArgPointee<5>(out_message),
+ SaveArg<3>(&scheme),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AsymmetricEncrypt(key_handle,
+ TPM_ALG_RSAES,
+ TPM_ALG_NULL,
+ plaintext,
+ nullptr,
+ &ciphertext));
+ EXPECT_EQ(scheme.scheme, TPM_ALG_RSAES);
+}
+
+TEST_F(TpmUtilityTest, AsymmetricDecryptSuccess) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string output_plaintext("plaintext");
+ std::string ciphertext;
+ std::string password("password");
+ TPM2B_PUBLIC_KEY_RSA out_message = Make_TPM2B_PUBLIC_KEY_RSA(
+ output_plaintext);
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_DecryptSync(key_handle, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SetArgPointee<5>(out_message),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AsymmetricDecrypt(
+ key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ ciphertext,
+ &mock_authorization_delegate_,
+ &plaintext));
+ EXPECT_EQ(0, plaintext.compare(output_plaintext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricDecryptFail) {
+ TPM_HANDLE key_handle;
+ std::string key_name;
+ std::string plaintext;
+ std::string ciphertext;
+ std::string password;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_DecryptSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.AsymmetricDecrypt(
+ key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ ciphertext,
+ &mock_authorization_delegate_,
+ &plaintext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricDecryptBadParams) {
+ TPM_HANDLE key_handle;
+ std::string key_name;
+ std::string plaintext;
+ std::string ciphertext;
+ std::string password;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt | kRestricted;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.AsymmetricDecrypt(
+ key_handle,
+ TPM_ALG_RSAES,
+ TPM_ALG_NULL,
+ ciphertext,
+ &mock_authorization_delegate_,
+ &plaintext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricDecryptBadSession) {
+ TPM_HANDLE key_handle = TPM_RH_FIRST;
+ std::string key_name;
+ std::string plaintext;
+ std::string ciphertext;
+ std::string password;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.AsymmetricDecrypt(
+ key_handle, TPM_ALG_RSAES, TPM_ALG_NULL,
+ ciphertext, nullptr, &plaintext));
+}
+
+TEST_F(TpmUtilityTest, AsymmetricDecryptNullSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string output_plaintext("plaintext");
+ std::string ciphertext;
+ std::string password;
+ TPM2B_PUBLIC_KEY_RSA out_message = Make_TPM2B_PUBLIC_KEY_RSA(
+ output_plaintext);
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ TPMT_RSA_DECRYPT scheme;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_DecryptSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<5>(out_message),
+ SaveArg<3>(&scheme),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AsymmetricDecrypt(
+ key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ ciphertext,
+ &mock_authorization_delegate_,
+ &plaintext));
+ EXPECT_EQ(scheme.scheme, TPM_ALG_OAEP);
+ EXPECT_EQ(scheme.details.oaep.hash_alg, TPM_ALG_SHA256);
+}
+
+TEST_F(TpmUtilityTest, AsymmetricDecryptSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string plaintext;
+ std::string output_plaintext("plaintext");
+ std::string ciphertext;
+ std::string password;
+ TPM2B_PUBLIC_KEY_RSA out_message = Make_TPM2B_PUBLIC_KEY_RSA(
+ output_plaintext);
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ TPMT_RSA_DECRYPT scheme;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, RSA_DecryptSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<5>(out_message),
+ SaveArg<3>(&scheme),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.AsymmetricDecrypt(
+ key_handle,
+ TPM_ALG_RSAES,
+ TPM_ALG_NULL,
+ ciphertext,
+ &mock_authorization_delegate_,
+ &plaintext));
+ EXPECT_EQ(scheme.scheme, TPM_ALG_RSAES);
+}
+
+TEST_F(TpmUtilityTest, SignSuccess) {
+ TPM_HANDLE key_handle;
+ std::string password("password");
+ std::string digest(32, 'a');
+ TPMT_SIGNATURE signature_out;
+ signature_out.signature.rsassa.sig.size = 2;
+ signature_out.signature.rsassa.sig.buffer[0] = 'h';
+ signature_out.signature.rsassa.sig.buffer[1] = 'i';
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, SignSync(key_handle, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SetArgPointee<5>(signature_out),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Sign(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+ EXPECT_EQ(0, signature.compare("hi"));
+}
+
+TEST_F(TpmUtilityTest, SignFail) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, SignSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Sign(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+}
+
+TEST_F(TpmUtilityTest, SignBadParams1) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign | kRestricted;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Sign(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+}
+
+TEST_F(TpmUtilityTest, SignBadAuthorizationSession) {
+ TPM_HANDLE key_handle = TPM_RH_FIRST;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.Sign(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_NULL,
+ digest,
+ nullptr,
+ &signature));
+}
+
+TEST_F(TpmUtilityTest, SignBadParams2) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Sign(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+}
+
+TEST_F(TpmUtilityTest, SignBadParams3) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_ECC;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Sign(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+}
+
+TEST_F(TpmUtilityTest, SignBadParams4) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_FAILURE)));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Sign(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+}
+
+TEST_F(TpmUtilityTest, SignBadParams5) {
+ TPM_HANDLE key_handle = 0;
+ std::string password;
+ std::string digest(32, 'a');
+ std::string signature;
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Sign(key_handle,
+ TPM_ALG_AES,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+}
+
+
+TEST_F(TpmUtilityTest, SignNullSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(32, 'a');
+ TPMT_SIGNATURE signature_out;
+ signature_out.signature.rsassa.sig.size = 0;
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ TPMT_SIG_SCHEME scheme;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, SignSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<5>(signature_out),
+ SaveArg<3>(&scheme),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Sign(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+ EXPECT_EQ(scheme.scheme, TPM_ALG_RSASSA);
+ EXPECT_EQ(scheme.details.rsassa.hash_alg, TPM_ALG_SHA256);
+}
+
+TEST_F(TpmUtilityTest, SignSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string password;
+ std::string digest(64, 'a');
+ TPMT_SIGNATURE signature_out;
+ signature_out.signature.rsassa.sig.size = 0;
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ TPMT_SIG_SCHEME scheme;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, SignSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<5>(signature_out),
+ SaveArg<3>(&scheme),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Sign(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_SHA1,
+ digest,
+ &mock_authorization_delegate_,
+ &signature));
+ EXPECT_EQ(scheme.scheme, TPM_ALG_RSAPSS);
+ EXPECT_EQ(scheme.details.rsapss.hash_alg, TPM_ALG_SHA1);
+}
+
+TEST_F(TpmUtilityTest, VerifySuccess) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, VerifySignatureSync(key_handle, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyFail) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, VerifySignatureSync(key_handle, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyBadParams1) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign | kRestricted;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyBadParams2) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kDecrypt;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyBadParams3) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_ECC;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyBadParams4) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_FAILURE)));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyBadParams5) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.Verify(key_handle,
+ TPM_ALG_AES,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, VerifyNullSchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string digest(32, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ TPMT_SIGNATURE signature_in;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, VerifySignatureSync(key_handle, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<3>(&signature_in),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Verify(key_handle,
+ TPM_ALG_NULL,
+ TPM_ALG_NULL,
+ digest,
+ signature,
+ nullptr));
+ EXPECT_EQ(signature_in.sig_alg, TPM_ALG_RSASSA);
+ EXPECT_EQ(signature_in.signature.rsassa.hash, TPM_ALG_SHA256);
+}
+
+TEST_F(TpmUtilityTest, VerifySchemeForward) {
+ TPM_HANDLE key_handle;
+ std::string digest(64, 'a');
+ std::string signature;
+ TPM2B_PUBLIC public_area;
+ TPMT_SIGNATURE signature_in;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.object_attributes = kSign;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, VerifySignatureSync(key_handle, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<3>(&signature_in),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.Verify(key_handle,
+ TPM_ALG_RSAPSS,
+ TPM_ALG_SHA1,
+ digest,
+ signature,
+ nullptr));
+ EXPECT_EQ(signature_in.sig_alg, TPM_ALG_RSAPSS);
+ EXPECT_EQ(signature_in.signature.rsassa.hash, TPM_ALG_SHA1);
+}
+
+TEST_F(TpmUtilityTest, CertifyCreationSuccess) {
+ TPM_HANDLE key_handle = 42;
+ std::string creation_blob;
+ EXPECT_CALL(mock_tpm_, CertifyCreationSyncShort(TPM_RH_NULL, key_handle,
+ _, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.CertifyCreation(key_handle, creation_blob));
+}
+
+TEST_F(TpmUtilityTest, CertifyCreationParserError) {
+ TPM_HANDLE key_handle = 42;
+ std::string creation_blob;
+ EXPECT_CALL(mock_blob_parser_, ParseCreationBlob(creation_blob, _, _, _))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER,
+ utility_.CertifyCreation(key_handle, creation_blob));
+}
+
+TEST_F(TpmUtilityTest, CertifyCreationFailure) {
+ TPM_HANDLE key_handle = 42;
+ std::string creation_blob;
+ EXPECT_CALL(mock_tpm_, CertifyCreationSyncShort(TPM_RH_NULL, key_handle,
+ _, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.CertifyCreation(key_handle, creation_blob));
+}
+
+TEST_F(TpmUtilityTest, ChangeAuthDataSuccess) {
+ TPM_HANDLE key_handle = 1;
+ std::string new_password;
+ std::string key_blob;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ChangeKeyAuthorizationData(
+ key_handle, new_password, &mock_authorization_delegate_, &key_blob));
+}
+
+TEST_F(TpmUtilityTest, ChangeAuthDataKeyNameFail) {
+ TPM_HANDLE key_handle = 1;
+ std::string old_password;
+ std::string new_password;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(key_handle, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ChangeKeyAuthorizationData(
+ key_handle, new_password, &mock_authorization_delegate_, nullptr));
+}
+
+TEST_F(TpmUtilityTest, ChangeAuthDataFailure) {
+ TPM_HANDLE key_handle = 1;
+ std::string new_password;
+ EXPECT_CALL(mock_tpm_, ObjectChangeAuthSync(key_handle, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ChangeKeyAuthorizationData(
+ key_handle, new_password, &mock_authorization_delegate_, nullptr));
+}
+
+TEST_F(TpmUtilityTest, ChangeAuthDataParserFail) {
+ TPM_HANDLE key_handle = 1;
+ std::string new_password;
+ std::string key_blob;
+ TPM2B_PUBLIC public_area;
+ public_area.public_area.type = TPM_ALG_RSA;
+ public_area.public_area.auth_policy.size = 0;
+ public_area.public_area.unique.rsa.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_blob_parser_, SerializeKeyBlob(_, _, &key_blob))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_TCTI_STRUCTURE, utility_.ChangeKeyAuthorizationData(
+ key_handle, new_password, &mock_authorization_delegate_, &key_blob));
+}
+
+TEST_F(TpmUtilityTest, ImportRSAKeySuccess) {
+ uint32_t public_exponent = 0x10001;
+ std::string modulus(256, 'a');
+ std::string prime_factor(128, 'b');
+ std::string password("password");
+ std::string key_blob;
+ TPM2B_DATA encryption_key;
+ TPM2B_PUBLIC public_data;
+ TPM2B_PRIVATE private_data;
+ EXPECT_CALL(mock_tpm_, ImportSync(_, _, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<2>(&encryption_key),
+ SaveArg<3>(&public_data),
+ SaveArg<4>(&private_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey,
+ modulus,
+ public_exponent,
+ prime_factor,
+ password,
+ &mock_authorization_delegate_,
+ &key_blob));
+ // Validate that the public area was properly constructed.
+ EXPECT_EQ(public_data.public_area.parameters.rsa_detail.key_bits,
+ modulus.size() * 8);
+ EXPECT_EQ(public_data.public_area.parameters.rsa_detail.exponent,
+ public_exponent);
+ EXPECT_EQ(public_data.public_area.unique.rsa.size, modulus.size());
+ EXPECT_EQ(0, memcmp(public_data.public_area.unique.rsa.buffer,
+ modulus.data(), modulus.size()));
+ // Validate the private struct construction.
+ EXPECT_EQ(kAesKeySize, encryption_key.size);
+ AES_KEY key;
+ AES_set_encrypt_key(encryption_key.buffer, kAesKeySize * 8, &key);
+ unsigned char iv[MAX_AES_BLOCK_SIZE_BYTES] = {0};
+ int iv_in = 0;
+ std::string unencrypted_private(private_data.size, 0);
+ AES_cfb128_encrypt(
+ reinterpret_cast<const unsigned char*>(private_data.buffer),
+ reinterpret_cast<unsigned char*>(string_as_array(&unencrypted_private)),
+ private_data.size, &key, iv, &iv_in, AES_DECRYPT);
+ TPM2B_DIGEST inner_integrity;
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPM2B_DIGEST(&unencrypted_private,
+ &inner_integrity, nullptr));
+ std::string object_name;
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ ComputeKeyName(public_data.public_area, &object_name));
+ std::string integrity_value = crypto::SHA256HashString(unencrypted_private +
+ object_name);
+ EXPECT_EQ(integrity_value.size(), inner_integrity.size);
+ EXPECT_EQ(0, memcmp(inner_integrity.buffer,
+ integrity_value.data(),
+ inner_integrity.size));
+ TPM2B_SENSITIVE sensitive_data;
+ EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPM2B_SENSITIVE(&unencrypted_private,
+ &sensitive_data, nullptr));
+ EXPECT_EQ(sensitive_data.sensitive_area.auth_value.size, password.size());
+ EXPECT_EQ(0, memcmp(sensitive_data.sensitive_area.auth_value.buffer,
+ password.data(), password.size()));
+ EXPECT_EQ(sensitive_data.sensitive_area.sensitive.rsa.size,
+ prime_factor.size());
+ EXPECT_EQ(0, memcmp(sensitive_data.sensitive_area.sensitive.rsa.buffer,
+ prime_factor.data(), prime_factor.size()));
+}
+
+TEST_F(TpmUtilityTest, ImportRSAKeySuccessWithNoBlob) {
+ uint32_t public_exponent = 0x10001;
+ std::string modulus(256, 'a');
+ std::string prime_factor(128, 'b');
+ std::string password;
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey,
+ modulus,
+ public_exponent,
+ prime_factor,
+ password,
+ &mock_authorization_delegate_,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, ImportRSAKeyParentNameFail) {
+ uint32_t public_exponent = 0x10001;
+ std::string modulus(256, 'a');
+ std::string prime_factor(128, 'b');
+ std::string password;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey,
+ modulus,
+ public_exponent,
+ prime_factor,
+ password,
+ &mock_authorization_delegate_,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, ImportRSAKeyFail) {
+ std::string modulus;
+ std::string prime_factor;
+ std::string password;
+ EXPECT_CALL(mock_tpm_, ImportSync(_, _, _, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey,
+ modulus,
+ 0x10001,
+ prime_factor,
+ password,
+ &mock_authorization_delegate_,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, ImportRSAKeyParserFail) {
+ std::string modulus;
+ std::string prime_factor;
+ std::string password;
+ std::string key_blob;
+ EXPECT_CALL(mock_blob_parser_, SerializeKeyBlob(_, _, &key_blob))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_TCTI_STRUCTURE, utility_.ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey,
+ modulus,
+ 0x10001,
+ prime_factor,
+ password,
+ &mock_authorization_delegate_,
+ &key_blob));
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairSuccess) {
+ TPM2B_PUBLIC public_area;
+ TPML_PCR_SELECTION creation_pcrs;
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(kRSAStorageRootKey,
+ _, _, _, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SaveArg<2>(&public_area),
+ SaveArg<3>(&creation_pcrs),
+ Return(TPM_RC_SUCCESS)));
+ std::string key_blob;
+ std::string creation_blob;
+ int creation_pcr = 12;
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
+ "password", "", false, creation_pcr, &mock_authorization_delegate_,
+ &key_blob, &creation_blob));
+ EXPECT_EQ(public_area.public_area.object_attributes & kDecrypt, kDecrypt);
+ EXPECT_EQ(public_area.public_area.object_attributes & kSign, kSign);
+ EXPECT_EQ(public_area.public_area.object_attributes & kUserWithAuth,
+ kUserWithAuth);
+ EXPECT_EQ(public_area.public_area.object_attributes & kAdminWithPolicy, 0);
+ EXPECT_EQ(public_area.public_area.parameters.rsa_detail.scheme.scheme,
+ TPM_ALG_NULL);
+ EXPECT_EQ(1, creation_pcrs.count);
+ EXPECT_EQ(TPM_ALG_SHA256, creation_pcrs.pcr_selections[0].hash);
+ EXPECT_EQ(PCR_SELECT_MIN, creation_pcrs.pcr_selections[0].sizeof_select);
+ EXPECT_EQ(1 << (creation_pcr % 8),
+ creation_pcrs.pcr_selections[0].pcr_select[creation_pcr / 8]);
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairDecryptKeySuccess) {
+ TPM2B_PUBLIC public_area;
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(kRSAStorageRootKey,
+ _, _, _, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SaveArg<2>(&public_area),
+ Return(TPM_RC_SUCCESS)));
+ std::string key_blob;
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "password",
+ "", false, kNoCreationPCR, &mock_authorization_delegate_, &key_blob,
+ nullptr));
+ EXPECT_EQ(public_area.public_area.object_attributes & kDecrypt, kDecrypt);
+ EXPECT_EQ(public_area.public_area.object_attributes & kSign, 0);
+ EXPECT_EQ(public_area.public_area.parameters.rsa_detail.scheme.scheme,
+ TPM_ALG_NULL);
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairSignKeySuccess) {
+ TPM2B_PUBLIC public_area;
+ TPM2B_SENSITIVE_CREATE sensitive_create;
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(kRSAStorageRootKey,
+ _, _, _, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SaveArg<1>(&sensitive_create),
+ SaveArg<2>(&public_area),
+ Return(TPM_RC_SUCCESS)));
+ std::string key_blob;
+ std::string policy_digest(32, 'a');
+ std::string key_auth("password");
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, key_auth,
+ policy_digest, true /* use_only_policy_authorization */, kNoCreationPCR,
+ &mock_authorization_delegate_, &key_blob, nullptr));
+ EXPECT_EQ(public_area.public_area.object_attributes & kDecrypt, 0);
+ EXPECT_EQ(public_area.public_area.object_attributes & kSign, kSign);
+ EXPECT_EQ(public_area.public_area.object_attributes & kUserWithAuth, 0);
+ EXPECT_EQ(public_area.public_area.object_attributes & kAdminWithPolicy,
+ kAdminWithPolicy);
+ EXPECT_EQ(public_area.public_area.parameters.rsa_detail.scheme.scheme,
+ TPM_ALG_NULL);
+ EXPECT_EQ(public_area.public_area.parameters.rsa_detail.key_bits, 2048);
+ EXPECT_EQ(public_area.public_area.parameters.rsa_detail.exponent, 0x10001);
+ EXPECT_EQ(public_area.public_area.auth_policy.size, policy_digest.size());
+ EXPECT_EQ(0, memcmp(public_area.public_area.auth_policy.buffer,
+ policy_digest.data(), policy_digest.size()));
+ EXPECT_EQ(sensitive_create.sensitive.user_auth.size, key_auth.size());
+ EXPECT_EQ(0, memcmp(sensitive_create.sensitive.user_auth.buffer,
+ key_auth.data(), key_auth.size()));
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairBadDelegate) {
+ std::string key_blob;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "password",
+ "", false, kNoCreationPCR, nullptr, &key_blob, nullptr));
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairFailure) {
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(kRSAStorageRootKey,
+ _, _, _, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ std::string key_blob;
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, "password",
+ "", false, kNoCreationPCR, &mock_authorization_delegate_, &key_blob,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairKeyParserFail) {
+ std::string key_blob;
+ EXPECT_CALL(mock_blob_parser_, SerializeKeyBlob(_, _, &key_blob))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_TCTI_STRUCTURE, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, "password",
+ "", false, kNoCreationPCR, &mock_authorization_delegate_, &key_blob,
+ nullptr));
+}
+
+TEST_F(TpmUtilityTest, CreateRSAKeyPairCreationParserFail) {
+ std::string creation_blob;
+ std::string key_blob;
+ EXPECT_CALL(mock_blob_parser_, SerializeCreationBlob(_, _, _, &creation_blob))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_TCTI_STRUCTURE, utility_.CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, "password",
+ "", false, kNoCreationPCR, &mock_authorization_delegate_, &key_blob,
+ &creation_blob));
+}
+
+TEST_F(TpmUtilityTest, LoadKeySuccess) {
+ TPM_HANDLE key_handle = TPM_RH_FIRST;
+ TPM_HANDLE loaded_handle;
+ EXPECT_CALL(mock_tpm_, LoadSync(kRSAStorageRootKey, _, _, _, _, _,
+ &mock_authorization_delegate_))
+ .WillOnce(DoAll(SetArgPointee<4>(key_handle),
+ Return(TPM_RC_SUCCESS)));
+ std::string key_blob;
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.LoadKey(
+ key_blob, &mock_authorization_delegate_, &loaded_handle));
+ EXPECT_EQ(loaded_handle, key_handle);
+}
+
+TEST_F(TpmUtilityTest, LoadKeyFailure) {
+ TPM_HANDLE key_handle;
+ EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ std::string key_blob;
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.LoadKey(
+ key_blob, &mock_authorization_delegate_, &key_handle));
+}
+
+TEST_F(TpmUtilityTest, LoadKeyBadDelegate) {
+ TPM_HANDLE key_handle;
+ std::string key_blob;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.LoadKey(
+ key_blob, nullptr, &key_handle));
+}
+
+TEST_F(TpmUtilityTest, LoadKeyParserFail) {
+ TPM_HANDLE key_handle;
+ std::string key_blob;
+ EXPECT_CALL(mock_blob_parser_, ParseKeyBlob(key_blob, _, _))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_TCTI_STRUCTURE, utility_.LoadKey(
+ key_blob, &mock_authorization_delegate_, &key_handle));
+}
+
+TEST_F(TpmUtilityTest, SealedDataSuccess) {
+ std::string data_to_seal("seal_data");
+ std::string sealed_data;
+ TPM2B_SENSITIVE_CREATE sensitive_create;
+ TPM2B_PUBLIC in_public;
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(kRSAStorageRootKey, _, _,
+ _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<1>(&sensitive_create),
+ SaveArg<2>(&in_public),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.SealData(
+ data_to_seal, "", &mock_authorization_delegate_, &sealed_data));
+ EXPECT_EQ(sensitive_create.sensitive.data.size, data_to_seal.size());
+ EXPECT_EQ(0, memcmp(sensitive_create.sensitive.data.buffer,
+ data_to_seal.data(), data_to_seal.size()));
+ EXPECT_EQ(in_public.public_area.type, TPM_ALG_KEYEDHASH);
+ EXPECT_EQ(in_public.public_area.name_alg, TPM_ALG_SHA256);
+}
+
+TEST_F(TpmUtilityTest, SealDataBadDelegate) {
+ std::string data_to_seal("seal_data");
+ std::string sealed_data;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.SealData(
+ data_to_seal, "", nullptr, &sealed_data));
+}
+
+TEST_F(TpmUtilityTest, SealDataFailure) {
+ std::string data_to_seal("seal_data");
+ std::string sealed_data;
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(kRSAStorageRootKey, _, _,
+ _, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.SealData(
+ data_to_seal, "", &mock_authorization_delegate_, &sealed_data));
+}
+
+TEST_F(TpmUtilityTest, SealDataParserFail) {
+ std::string data_to_seal("seal_data");
+ std::string sealed_data;
+ EXPECT_CALL(mock_blob_parser_, SerializeKeyBlob(_, _, &sealed_data))
+ .WillOnce(Return(false));
+ EXPECT_EQ(SAPI_RC_BAD_TCTI_STRUCTURE, utility_.SealData(
+ data_to_seal, "", &mock_authorization_delegate_, &sealed_data));
+}
+
+TEST_F(TpmUtilityTest, UnsealDataSuccess) {
+ std::string sealed_data;
+ std::string tpm_unsealed_data("password");
+ std::string unsealed_data;
+ TPM_HANDLE object_handle = 42;
+ TPM2B_PUBLIC public_data;
+ public_data.public_area.auth_policy.size = 0;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(object_handle, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(public_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(object_handle),
+ Return(TPM_RC_SUCCESS)));
+ TPM2B_SENSITIVE_DATA out_data = Make_TPM2B_SENSITIVE_DATA(tpm_unsealed_data);
+ EXPECT_CALL(mock_tpm_, UnsealSync(object_handle, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<2>(out_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.UnsealData(
+ sealed_data, &mock_authorization_delegate_, &unsealed_data));
+ EXPECT_EQ(unsealed_data, tpm_unsealed_data);
+}
+
+TEST_F(TpmUtilityTest, UnsealDataBadDelegate) {
+ std::string sealed_data;
+ std::string unsealed_data;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.UnsealData(
+ sealed_data, nullptr, &unsealed_data));
+}
+
+TEST_F(TpmUtilityTest, UnsealDataLoadFail) {
+ std::string sealed_data;
+ std::string unsealed_data;
+ EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.UnsealData(
+ sealed_data, &mock_authorization_delegate_, &unsealed_data));
+}
+
+TEST_F(TpmUtilityTest, UnsealDataBadKeyName) {
+ std::string sealed_data;
+ std::string unsealed_data;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.UnsealData(
+ sealed_data, &mock_authorization_delegate_, &unsealed_data));
+}
+
+TEST_F(TpmUtilityTest, UnsealObjectFailure) {
+ std::string sealed_data;
+ std::string unsealed_data;
+ EXPECT_CALL(mock_tpm_, UnsealSync(_, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.UnsealData(
+ sealed_data, &mock_authorization_delegate_, &unsealed_data));
+}
+
+TEST_F(TpmUtilityTest, StartSessionSuccess) {
+ EXPECT_CALL(mock_hmac_session_, StartUnboundSession(true))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.StartSession(&mock_hmac_session_));
+}
+
+TEST_F(TpmUtilityTest, StartSessionFailure) {
+ EXPECT_CALL(mock_hmac_session_, StartUnboundSession(true))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.StartSession(&mock_hmac_session_));
+}
+
+TEST_F(TpmUtilityTest, GetPolicyDigestForPcrValueSuccess) {
+ int index = 5;
+ std::string pcr_value("pcr_value");
+ std::string policy_digest;
+ TPML_PCR_SELECTION pcr_select;
+ pcr_select.count = 1;
+ pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
+ pcr_select.pcr_selections[0].sizeof_select = 1;
+ pcr_select.pcr_selections[0].pcr_select[index / 8] = 1 << (index % 8);
+ TPML_DIGEST pcr_values;
+ pcr_values.count = 1;
+ pcr_values.digests[0] = Make_TPM2B_DIGEST(pcr_value);
+ EXPECT_CALL(mock_tpm_, PCR_ReadSync(_, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<2>(pcr_select),
+ SetArgPointee<3>(pcr_values),
+ Return(TPM_RC_SUCCESS)));
+ std::string tpm_pcr_value;
+ EXPECT_CALL(mock_policy_session_, PolicyPCR(index, _))
+ .WillOnce(DoAll(SaveArg<1>(&tpm_pcr_value),
+ Return(TPM_RC_SUCCESS)));
+ std::string tpm_policy_digest("digest");
+ EXPECT_CALL(mock_policy_session_, GetDigest(_))
+ .WillOnce(DoAll(SetArgPointee<0>(tpm_policy_digest),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.GetPolicyDigestForPcrValue(index, "", &policy_digest));
+ EXPECT_EQ(policy_digest, tpm_policy_digest);
+ EXPECT_EQ(pcr_value, tpm_pcr_value);
+}
+
+TEST_F(TpmUtilityTest, GetPolicyDigestForPcrValueSuccessWithPcrValue) {
+ int index = 5;
+ std::string pcr_value("pcr_value");
+ std::string policy_digest;
+ std::string tpm_pcr_value;
+ EXPECT_CALL(mock_policy_session_, PolicyPCR(index, _))
+ .WillOnce(DoAll(SaveArg<1>(&tpm_pcr_value),
+ Return(TPM_RC_SUCCESS)));
+ std::string tpm_policy_digest("digest");
+ EXPECT_CALL(mock_policy_session_, GetDigest(_))
+ .WillOnce(DoAll(SetArgPointee<0>(tpm_policy_digest),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.GetPolicyDigestForPcrValue(index, pcr_value, &policy_digest));
+ EXPECT_EQ(policy_digest, tpm_policy_digest);
+ EXPECT_EQ(pcr_value, tpm_pcr_value);
+}
+
+TEST_F(TpmUtilityTest, GetPolicyDigestForPcrValueBadSession) {
+ int index = 5;
+ std::string pcr_value("value");
+ std::string policy_digest;
+ EXPECT_CALL(mock_policy_session_, StartUnboundSession(false))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.GetPolicyDigestForPcrValue(index, pcr_value, &policy_digest));
+}
+
+TEST_F(TpmUtilityTest, GetPolicyDigestForPcrValuePcrReadFail) {
+ int index = 5;
+ std::string policy_digest;
+ EXPECT_CALL(mock_tpm_, PCR_ReadSync(_, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.GetPolicyDigestForPcrValue(index, "", &policy_digest));
+}
+
+TEST_F(TpmUtilityTest, GetPolicyDigestForPcrValueBadPcr) {
+ int index = 5;
+ std::string pcr_value("value");
+ std::string policy_digest;
+ EXPECT_CALL(mock_policy_session_, PolicyPCR(index, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.GetPolicyDigestForPcrValue(index, pcr_value, &policy_digest));
+}
+
+TEST_F(TpmUtilityTest, GetPolicyDigestForPcrValueBadDigest) {
+ int index = 5;
+ std::string pcr_value("value");
+ std::string policy_digest;
+ EXPECT_CALL(mock_policy_session_, GetDigest(&policy_digest))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.GetPolicyDigestForPcrValue(index, pcr_value, &policy_digest));
+}
+
+TEST_F(TpmUtilityTest, DefineNVSpaceSuccess) {
+ uint32_t index = 59;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ size_t length = 256;
+ TPM2B_NV_PUBLIC public_data;
+ EXPECT_CALL(mock_tpm_, NV_DefineSpaceSync(TPM_RH_OWNER, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<3>(&public_data),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.DefineNVSpace(
+ index, length, &mock_authorization_delegate_));
+ EXPECT_EQ(public_data.nv_public.nv_index, nvram_index);
+ EXPECT_EQ(public_data.nv_public.name_alg, TPM_ALG_SHA256);
+ EXPECT_EQ(public_data.nv_public.attributes,
+ TPMA_NV_OWNERWRITE | TPMA_NV_WRITEDEFINE | TPMA_NV_AUTHREAD);
+ EXPECT_EQ(public_data.nv_public.data_size, length);
+}
+
+TEST_F(TpmUtilityTest, DefineNVSpaceBadLength) {
+ size_t bad_length = 3000;
+ EXPECT_EQ(SAPI_RC_BAD_SIZE,
+ utility_.DefineNVSpace(0, bad_length, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, DefineNVSpaceBadIndex) {
+ uint32_t bad_index = 1<<29;
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER,
+ utility_.DefineNVSpace(bad_index, 2, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, DefineNVSpaceBadSession) {
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.DefineNVSpace(0, 2, nullptr));
+}
+
+TEST_F(TpmUtilityTest, DefineNVSpaceFail) {
+ uint32_t index = 59;
+ size_t length = 256;
+ EXPECT_CALL(mock_tpm_, NV_DefineSpaceSync(TPM_RH_OWNER, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.DefineNVSpace(index, length, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, DestroyNVSpaceSuccess) {
+ uint32_t index = 53;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ EXPECT_CALL(mock_tpm_,
+ NV_UndefineSpaceSync(TPM_RH_OWNER, _, nvram_index, _, _));
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.DestroyNVSpace(index, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, DestroyNVSpaceBadIndex) {
+ uint32_t bad_index = 1<<29;
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER,
+ utility_.DestroyNVSpace(bad_index, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, DestroyNVSpaceBadSession) {
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.DestroyNVSpace(3, nullptr));
+}
+
+TEST_F(TpmUtilityTest, DestroyNVSpaceFailure) {
+ uint32_t index = 53;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ EXPECT_CALL(mock_tpm_,
+ NV_UndefineSpaceSync(TPM_RH_OWNER, _, nvram_index, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.DestroyNVSpace(index, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, LockNVSpaceSuccess) {
+ uint32_t index = 53;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ EXPECT_CALL(mock_tpm_, NV_WriteLockSync(nvram_index, _, nvram_index, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS,
+ utility_.LockNVSpace(index, &mock_authorization_delegate_));
+ TPMS_NV_PUBLIC public_area;
+ EXPECT_EQ(TPM_RC_SUCCESS, GetNVRAMMap(index, &public_area));
+ EXPECT_EQ(public_area.attributes & TPMA_NV_WRITELOCKED, TPMA_NV_WRITELOCKED);
+}
+
+TEST_F(TpmUtilityTest, LockNVSpaceBadIndex) {
+ uint32_t bad_index = 1<<24;
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER,
+ utility_.LockNVSpace(bad_index, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, LockNVSpaceBadSession) {
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS, utility_.LockNVSpace(52, nullptr));
+}
+
+TEST_F(TpmUtilityTest, LockNVSpaceFailure) {
+ uint32_t index = 53;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ EXPECT_CALL(mock_tpm_, NV_WriteLockSync(nvram_index, _, nvram_index, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE,
+ utility_.LockNVSpace(index, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, WriteNVSpaceSuccess) {
+ uint32_t index = 53;
+ uint32_t offset = 5;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ EXPECT_CALL(mock_tpm_,
+ NV_WriteSync(TPM_RH_OWNER, _, nvram_index, _, _, offset, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.WriteNVSpace(
+ index, offset, "", &mock_authorization_delegate_));
+ TPMS_NV_PUBLIC public_area;
+ EXPECT_EQ(TPM_RC_SUCCESS, GetNVRAMMap(index, &public_area));
+ EXPECT_EQ(public_area.attributes & TPMA_NV_WRITTEN, TPMA_NV_WRITTEN);
+}
+
+TEST_F(TpmUtilityTest, WriteNVSpaceBadSize) {
+ uint32_t index = 53;
+ std::string nvram_data(1025, 0);
+ EXPECT_EQ(SAPI_RC_BAD_SIZE, utility_.WriteNVSpace(
+ index, 0, nvram_data, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, WriteNVSpaceBadIndex) {
+ uint32_t bad_index = 1<<24;
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.WriteNVSpace(
+ bad_index, 0, "", &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, WriteNVSpaceBadSessions) {
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS,
+ utility_.WriteNVSpace(53, 0, "", nullptr));
+}
+
+TEST_F(TpmUtilityTest, WriteNVSpaceFailure) {
+ uint32_t index = 53;
+ uint32_t offset = 5;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ EXPECT_CALL(mock_tpm_,
+ NV_WriteSync(TPM_RH_OWNER, _, nvram_index, _, _, offset, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.WriteNVSpace(
+ index, offset, "", &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, ReadNVSpaceSuccess) {
+ uint32_t index = 53;
+ uint32_t offset = 5;
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ size_t length = 24;
+ std::string nvram_data;
+ EXPECT_CALL(mock_tpm_,
+ NV_ReadSync(nv_index, _, nv_index, _, length, offset, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.ReadNVSpace(
+ index, offset, length, &nvram_data, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, ReadNVSpaceBadReadLength) {
+ size_t length = 1025;
+ std::string nvram_data;
+ EXPECT_EQ(SAPI_RC_BAD_SIZE, utility_.ReadNVSpace(
+ 52, 0, length, &nvram_data, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, ReadNVSpaceBadIndex) {
+ uint32_t bad_index = 1<<24;
+ std::string nvram_data;
+ EXPECT_EQ(SAPI_RC_BAD_PARAMETER, utility_.ReadNVSpace(
+ bad_index, 0, 5, &nvram_data, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, ReadNVSpaceBadSession) {
+ std::string nvram_data;
+ EXPECT_EQ(SAPI_RC_INVALID_SESSIONS,
+ utility_.ReadNVSpace(53, 0, 5, &nvram_data, nullptr));
+}
+
+TEST_F(TpmUtilityTest, ReadNVSpaceFailure) {
+ uint32_t index = 53;
+ uint32_t offset = 5;
+ uint32_t nv_index = NV_INDEX_FIRST + index;
+ size_t length = 24;
+ std::string nvram_data;
+ EXPECT_CALL(mock_tpm_,
+ NV_ReadSync(nv_index, _, nv_index, _, length, offset, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.ReadNVSpace(
+ index, offset, length, &nvram_data, &mock_authorization_delegate_));
+}
+
+TEST_F(TpmUtilityTest, GetNVSpaceNameSuccess) {
+ uint32_t index = 53;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ std::string name;
+ EXPECT_CALL(mock_tpm_, NV_ReadPublicSync(nvram_index, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.GetNVSpaceName(index, &name));
+}
+
+TEST_F(TpmUtilityTest, GetNVSpaceNameFailure) {
+ uint32_t index = 53;
+ std::string name;
+ EXPECT_CALL(mock_tpm_, NV_ReadPublicSync(_, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.GetNVSpaceName(index, &name));
+}
+
+TEST_F(TpmUtilityTest, GetNVSpacePublicAreaCachedSuccess) {
+ uint32_t index = 53;
+ TPMS_NV_PUBLIC public_area;
+ SetNVRAMMap(index, public_area);
+ EXPECT_CALL(mock_tpm_, NV_ReadPublicSync(_, _, _, _, _))
+ .Times(0);
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.GetNVSpacePublicArea(index, &public_area));
+}
+
+TEST_F(TpmUtilityTest, GetNVSpacePublicAreaSuccess) {
+ uint32_t index = 53;
+ uint32_t nvram_index = NV_INDEX_FIRST + index;
+ TPMS_NV_PUBLIC public_area;
+ EXPECT_CALL(mock_tpm_, NV_ReadPublicSync(nvram_index, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, utility_.GetNVSpacePublicArea(index, &public_area));
+}
+
+TEST_F(TpmUtilityTest, GetNVSpacePublicAreaFailure) {
+ uint32_t index = 53;
+ TPMS_NV_PUBLIC public_area;
+ EXPECT_CALL(mock_tpm_, NV_ReadPublicSync(_, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, utility_.GetNVSpacePublicArea(index, &public_area));
+}
+
+TEST_F(TpmUtilityTest, SetKnownPasswordSuccess) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillOnce(Return(false));
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_OWNER, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, SetKnownOwnerPassword("password"));
+}
+
+TEST_F(TpmUtilityTest, SetKnownPasswordOwnershipDone) {
+ EXPECT_EQ(TPM_RC_SUCCESS, SetKnownOwnerPassword("password"));
+}
+
+TEST_F(TpmUtilityTest, SetKnownPasswordFailure) {
+ EXPECT_CALL(mock_tpm_state_, IsOwnerPasswordSet())
+ .WillOnce(Return(false));
+ EXPECT_CALL(mock_tpm_, HierarchyChangeAuthSync(TPM_RH_OWNER, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, SetKnownOwnerPassword("password"));
+}
+
+TEST_F(TpmUtilityTest, RootKeysSuccess) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .Times(2)
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_SUCCESS, CreateStorageRootKeys("password"));
+}
+
+TEST_F(TpmUtilityTest, RootKeysHandleConsistency) {
+ TPM_HANDLE test_handle = 42;
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .Times(2)
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_CALL(mock_tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(test_handle),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, EvictControlSync(_, _, test_handle, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, CreateStorageRootKeys("password"));
+}
+
+TEST_F(TpmUtilityTest, RootKeysCreateFailure) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_CALL(mock_tpm_, CreatePrimarySyncShort(_, _, _, _, _, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, CreateStorageRootKeys("password"));
+}
+
+TEST_F(TpmUtilityTest, RootKeysPersistFailure) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_CALL(mock_tpm_, EvictControlSync(_, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, CreateStorageRootKeys("password"));
+}
+
+TEST_F(TpmUtilityTest, RootKeysAlreadyExist) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .Times(2)
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, CreateStorageRootKeys("password"));
+}
+
+TEST_F(TpmUtilityTest, SaltingKeySuccess) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ TPM2B_PUBLIC public_area;
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(_, _, _, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<2>(&public_area),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_EQ(TPM_RC_SUCCESS, CreateSaltingKey("password"));
+ EXPECT_EQ(TPM_ALG_SHA256, public_area.public_area.name_alg);
+}
+
+TEST_F(TpmUtilityTest, SaltingKeyConsistency) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ TPM_HANDLE test_handle = 42;
+ EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<4>(test_handle),
+ Return(TPM_RC_SUCCESS)));
+ EXPECT_CALL(mock_tpm_, EvictControlSync(_, _, test_handle, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, CreateSaltingKey("password"));
+}
+
+TEST_F(TpmUtilityTest, SaltingKeyCreateFailure) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_CALL(mock_tpm_, CreateSyncShort(_, _, _, _, _, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, CreateSaltingKey("password"));
+}
+
+TEST_F(TpmUtilityTest, SaltingKeyLoadFailure) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_CALL(mock_tpm_, LoadSync(_, _, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, CreateSaltingKey("password"));
+}
+
+TEST_F(TpmUtilityTest, SaltingKeyPersistFailure) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(_, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_FAILURE));
+ EXPECT_CALL(mock_tpm_, EvictControlSync(_, _, _, _, _, _))
+ .WillRepeatedly(Return(TPM_RC_FAILURE));
+ EXPECT_EQ(TPM_RC_FAILURE, CreateSaltingKey("password"));
+}
+
+TEST_F(TpmUtilityTest, SaltingKeyAlreadyExists) {
+ EXPECT_CALL(mock_tpm_, ReadPublicSync(kSaltingKey, _, _, _, _, _))
+ .WillOnce(Return(TPM_RC_SUCCESS));
+ EXPECT_EQ(TPM_RC_SUCCESS, CreateSaltingKey("password"));
+}
+
+} // namespace trunks
diff --git a/trunks/trunks.gyp b/trunks/trunks.gyp
new file mode 100644
index 0000000..d9c709c
--- /dev/null
+++ b/trunks/trunks.gyp
@@ -0,0 +1,183 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+{
+ 'target_defaults': {
+ 'includes': ['../../../platform2/common-mk/common.gypi'],
+ 'variables': {
+ 'deps': [ # This is a list of pkg-config dependencies
+ 'libbrillo-<(libbase_ver)',
+ 'libchrome-<(libbase_ver)',
+ 'openssl',
+ 'protobuf-lite',
+ ],
+ },
+ 'include_dirs': [
+ # We need this include dir because we include all the local code as
+ # "trunks/...".
+ '<(platform2_root)/../aosp/system/',
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'dbus_interface_proto',
+ 'type': 'static_library',
+ 'variables': {
+ 'proto_in_dir': '.',
+ 'proto_out_dir': 'include/trunks',
+ },
+ 'sources': [
+ '<(proto_in_dir)/dbus_interface.proto',
+ ],
+ 'includes': ['../../../platform2/common-mk/protoc.gypi'],
+ },
+ {
+ 'target_name': 'trunks',
+ 'type': 'shared_library',
+ 'sources': [
+ 'blob_parser.cc',
+ 'error_codes.cc',
+ 'hmac_authorization_delegate.cc',
+ 'hmac_session_impl.cc',
+ 'password_authorization_delegate.cc',
+ 'policy_session_impl.cc',
+ 'session_manager_impl.cc',
+ 'scoped_key_handle.cc',
+ 'tpm_generated.cc',
+ 'tpm_state_impl.cc',
+ 'tpm_utility_impl.cc',
+ 'trunks_factory_impl.cc',
+ 'trunks_proxy.cc',
+ ],
+ 'dependencies': [
+ 'dbus_interface_proto',
+ ],
+ 'conditions': [
+ ['USE_ftdi_tpm == 1', {
+ 'sources': [
+ 'ftdi/mpsse.c',
+ 'ftdi/support.c',
+ 'trunks_ftdi_spi.cc',
+ ],
+ 'libraries': [
+ '-lftdi1',
+ ],
+ 'defines': [
+ 'SPI_OVER_FTDI=1',
+ ],
+ },
+ ],
+ ],
+ },
+ {
+ 'target_name': 'trunks_test',
+ 'type': 'static_library',
+ 'standalone_static_library': 1,
+ 'sources': [
+ 'mock_authorization_delegate.cc',
+ 'mock_blob_parser.cc',
+ 'mock_command_transceiver.cc',
+ 'mock_hmac_session.cc',
+ 'mock_policy_session.cc',
+ 'mock_session_manager.cc',
+ 'mock_tpm.cc',
+ 'mock_tpm_state.cc',
+ 'mock_tpm_utility.cc',
+ 'trunks_factory_for_test.cc',
+ ],
+ },
+ {
+ 'target_name': 'trunks_client',
+ 'type': 'executable',
+ 'sources': [
+ 'trunks_client.cc',
+ 'trunks_client_test.cc',
+ ],
+ 'dependencies': [
+ 'trunks',
+ ],
+ },
+ {
+ 'target_name': 'trunksd_lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'background_command_transceiver.cc',
+ 'resource_manager.cc',
+ 'tpm_handle.cc',
+ 'tpm_simulator_handle.cc',
+ 'trunks_service.cc',
+ ],
+ 'dependencies': [
+ 'dbus_interface_proto',
+ ],
+ },
+ {
+ 'target_name': 'trunksd',
+ 'type': 'executable',
+ 'sources': [
+ 'trunksd.cc',
+ ],
+ 'variables': {
+ 'deps': [
+ 'libminijail',
+ ],
+ },
+ 'dependencies': [
+ 'dbus_interface_proto',
+ 'trunks',
+ 'trunksd_lib',
+ ],
+ 'conditions': [
+ ['USE_ftdi_tpm == 1', {
+ 'defines': [
+ 'SPI_OVER_FTDI=1',
+ ],
+ },
+ ],
+ ],
+ },
+ ],
+ 'conditions': [
+ ['USE_test == 1', {
+ 'targets': [
+ {
+ 'target_name': 'trunks_testrunner',
+ 'type': 'executable',
+ 'includes': ['../../../platform2/common-mk/common_test.gypi'],
+ 'sources': [
+ 'background_command_transceiver_test.cc',
+ 'hmac_authorization_delegate_test.cc',
+ 'hmac_session_test.cc',
+ 'password_authorization_delegate_test.cc',
+ 'policy_session_test.cc',
+ 'resource_manager_test.cc',
+ 'scoped_key_handle_test.cc',
+ 'session_manager_test.cc',
+ 'tpm_generated_test.cc',
+ 'tpm_state_test.cc',
+ 'tpm_utility_test.cc',
+ 'trunks_testrunner.cc',
+ ],
+ 'dependencies': [
+ 'trunks',
+ 'trunks_test',
+ 'trunksd_lib',
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/trunks/trunks_client.cc b/trunks/trunks_client.cc
new file mode 100644
index 0000000..4975470
--- /dev/null
+++ b/trunks/trunks_client.cc
@@ -0,0 +1,253 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+// trunks_client is a command line tool that supports various TPM operations. It
+// does not provide direct access to the trunksd D-Bus interface.
+
+#include <stdio.h>
+#include <string>
+
+#include <base/command_line.h>
+#include <base/logging.h>
+#include <brillo/syslog_logging.h>
+
+#include "trunks/error_codes.h"
+#include "trunks/hmac_session.h"
+#include "trunks/password_authorization_delegate.h"
+#include "trunks/policy_session.h"
+#include "trunks/scoped_key_handle.h"
+#include "trunks/tpm_state.h"
+#include "trunks/tpm_utility.h"
+#include "trunks/trunks_client_test.h"
+#include "trunks/trunks_factory_impl.h"
+#include "trunks/trunks_proxy.h"
+
+namespace {
+
+using trunks::CommandTransceiver;
+using trunks::TrunksFactory;
+
+void PrintUsage() {
+ puts("Options:");
+ puts(" --allocate_pcr - Configures PCR 0-15 under the SHA256 bank.");
+ puts(" --clear - Clears the TPM. Use before initializing the TPM.");
+ puts(" --help - Prints this message.");
+ puts(" --init_tpm - Initializes a TPM as CrOS firmware does.");
+ puts(" --own - Takes ownership of the TPM with the provided password.");
+ puts(" --owner_password - used to provide an owner password");
+ puts(" --regression_test - Runs some basic regression tests. If");
+ puts(" owner_password is supplied, it runs tests that");
+ puts(" need owner permissions.");
+ puts(" --startup - Performs startup and self-tests.");
+ puts(" --status - Prints TPM status information.");
+ puts(" --stress_test - Runs some basic stress tests.");
+}
+
+int Startup(TrunksFactory* factory) {
+ factory->GetTpmUtility()->Shutdown();
+ return factory->GetTpmUtility()->Startup();
+}
+
+int Clear(TrunksFactory* factory) {
+ return factory->GetTpmUtility()->Clear();
+}
+
+int InitializeTpm(TrunksFactory* factory) {
+ return factory->GetTpmUtility()->InitializeTpm();
+}
+
+int AllocatePCR(TrunksFactory* factory) {
+ trunks::TPM_RC result;
+ result = factory->GetTpmUtility()->AllocatePCR("");
+ if (result != trunks::TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error allocating PCR:" << trunks::GetErrorString(result);
+ return result;
+ }
+ factory->GetTpmUtility()->Shutdown();
+ return factory->GetTpmUtility()->Startup();
+}
+
+int TakeOwnership(const std::string& owner_password, TrunksFactory* factory) {
+ trunks::TPM_RC rc;
+ rc = factory->GetTpmUtility()->TakeOwnership(owner_password,
+ owner_password,
+ owner_password);
+ if (rc) {
+ LOG(ERROR) << "Error taking ownership: " << trunks::GetErrorString(rc);
+ return rc;
+ }
+ return 0;
+}
+
+int DumpStatus(TrunksFactory* factory) {
+ scoped_ptr<trunks::TpmState> state = factory->GetTpmState();
+ trunks::TPM_RC result = state->Initialize();
+ if (result != trunks::TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Failed to read TPM state: "
+ << trunks::GetErrorString(result);
+ return result;
+ }
+ printf("Owner password set: %s\n",
+ state->IsOwnerPasswordSet() ? "true" : "false");
+ printf("Endorsement password set: %s\n",
+ state->IsEndorsementPasswordSet() ? "true" : "false");
+ printf("Lockout password set: %s\n",
+ state->IsLockoutPasswordSet() ? "true" : "false");
+ printf("Ownership status: %s\n",
+ state->IsOwned() ? "true" : "false");
+ printf("In lockout: %s\n",
+ state->IsInLockout() ? "true" : "false");
+ printf("Platform hierarchy enabled: %s\n",
+ state->IsPlatformHierarchyEnabled() ? "true" : "false");
+ printf("Storage hierarchy enabled: %s\n",
+ state->IsStorageHierarchyEnabled() ? "true" : "false");
+ printf("Endorsement hierarchy enabled: %s\n",
+ state->IsEndorsementHierarchyEnabled() ? "true" : "false");
+ printf("Is Tpm enabled: %s\n",
+ state->IsEnabled() ? "true" : "false");
+ printf("Was shutdown orderly: %s\n",
+ state->WasShutdownOrderly() ? "true" : "false");
+ printf("Is RSA supported: %s\n",
+ state->IsRSASupported() ? "true" : "false");
+ printf("Is ECC supported: %s\n",
+ state->IsECCSupported() ? "true" : "false");
+ printf("Lockout Counter: %u\n", state->GetLockoutCounter());
+ printf("Lockout Threshold: %u\n", state->GetLockoutThreshold());
+ printf("Lockout Interval: %u\n", state->GetLockoutInterval());
+ printf("Lockout Recovery: %u\n", state->GetLockoutRecovery());
+ return 0;
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ base::CommandLine::Init(argc, argv);
+ brillo::InitLog(brillo::kLogToStderr);
+ base::CommandLine *cl = base::CommandLine::ForCurrentProcess();
+ if (cl->HasSwitch("help")) {
+ puts("Trunks Client: A command line tool to access the TPM.");
+ PrintUsage();
+ return 0;
+ }
+
+ CommandTransceiver* proxy = new trunks::TrunksProxy();
+
+ if (!proxy->Init()) {
+ LOG(ERROR) << "Error initializing proxy to communicate with TPM.";
+ return -1;
+ }
+ scoped_ptr<TrunksFactory> factory = scoped_ptr<TrunksFactory>(
+ new trunks::TrunksFactoryImpl(proxy));
+
+ if (cl->HasSwitch("status")) {
+ return DumpStatus(factory.get());
+ }
+ if (cl->HasSwitch("startup")) {
+ return Startup(factory.get());
+ }
+ if (cl->HasSwitch("clear")) {
+ return Clear(factory.get());
+ }
+ if (cl->HasSwitch("init_tpm")) {
+ return InitializeTpm(factory.get());
+ }
+ if (cl->HasSwitch("allocate_pcr")) {
+ return AllocatePCR(factory.get());
+ }
+
+ if (cl->HasSwitch("own")) {
+ return TakeOwnership(cl->GetSwitchValueASCII("owner_password"),
+ factory.get());
+ }
+ if (cl->HasSwitch("regression_test")) {
+ trunks::TrunksClientTest test;
+ LOG(INFO) << "Running RNG test.";
+ if (!test.RNGTest()) {
+ LOG(ERROR) << "Error running RNGtest.";
+ return -1;
+ }
+ LOG(INFO) << "Running RSA key tests.";
+ if (!test.SignTest()) {
+ LOG(ERROR) << "Error running SignTest.";
+ return -1;
+ }
+ if (!test.DecryptTest()) {
+ LOG(ERROR) << "Error running DecryptTest.";
+ return -1;
+ }
+ if (!test.ImportTest()) {
+ LOG(ERROR) << "Error running ImportTest.";
+ return -1;
+ }
+ if (!test.AuthChangeTest()) {
+ LOG(ERROR) << "Error running AuthChangeTest.";
+ return -1;
+ }
+ if (!test.VerifyKeyCreationTest()) {
+ LOG(ERROR) << "Error running VerifyKeyCreationTest.";
+ return -1;
+ }
+ LOG(INFO) << "Running Sealed Data test.";
+ if (!test.SealedDataTest()) {
+ LOG(ERROR) << "Error running SealedDataTest.";
+ return -1;
+ }
+ LOG(INFO) << "Running PCR test.";
+ if (!test.PCRTest()) {
+ LOG(ERROR) << "Error running PCRTest.";
+ return -1;
+ }
+ LOG(INFO) << "Running policy tests.";
+ if (!test.PolicyAuthValueTest()) {
+ LOG(ERROR) << "Error running PolicyAuthValueTest.";
+ return -1;
+ }
+ if (!test.PolicyAndTest()) {
+ LOG(ERROR) << "Error running PolicyAndTest.";
+ return -1;
+ }
+ if (!test.PolicyOrTest()) {
+ LOG(ERROR) << "Error running PolicyOrTest.";
+ return -1;
+ }
+ if (cl->HasSwitch("owner_password")) {
+ std::string owner_password = cl->GetSwitchValueASCII("owner_password");
+ LOG(INFO) << "Running NVRAM test.";
+ if (!test.NvramTest(owner_password)) {
+ LOG(ERROR) << "Error running NvramTest.";
+ return -1;
+ }
+ }
+ LOG(INFO) << "All tests were run successfully.";
+ return 0;
+ }
+ if (cl->HasSwitch("stress_test")) {
+ LOG(INFO) << "Running stress tests.";
+ trunks::TrunksClientTest test;
+ if (!test.ManyKeysTest()) {
+ LOG(ERROR) << "Error running ManyKeysTest.";
+ return -1;
+ }
+ if (!test.ManySessionsTest()) {
+ LOG(ERROR) << "Error running ManySessionsTest.";
+ return -1;
+ }
+ return 0;
+ }
+ puts("Invalid options!");
+ PrintUsage();
+ return -1;
+}
diff --git a/trunks/trunks_client_test.cc b/trunks/trunks_client_test.cc
new file mode 100644
index 0000000..73b8a0c
--- /dev/null
+++ b/trunks/trunks_client_test.cc
@@ -0,0 +1,1058 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/trunks_client_test.h"
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+#include <base/stl_util.h>
+#include <crypto/scoped_openssl_types.h>
+#include <crypto/sha2.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/error_codes.h"
+#include "trunks/hmac_session.h"
+#include "trunks/policy_session.h"
+#include "trunks/scoped_key_handle.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/tpm_state.h"
+#include "trunks/tpm_utility.h"
+#include "trunks/trunks_factory_impl.h"
+
+namespace trunks {
+
+TrunksClientTest::TrunksClientTest() : factory_(new TrunksFactoryImpl()) {}
+
+TrunksClientTest::TrunksClientTest(scoped_ptr<TrunksFactory> factory)
+ : factory_(factory.Pass()) {}
+
+TrunksClientTest::~TrunksClientTest() {}
+
+bool TrunksClientTest::RNGTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ std::string entropy_data("entropy_data");
+ std::string random_data;
+ size_t num_bytes = 70;
+ TPM_RC result = utility->StirRandom(entropy_data, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error stirring TPM RNG: " << GetErrorString(result);
+ return false;
+ }
+ result = utility->GenerateRandom(num_bytes, session->GetDelegate(),
+ &random_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting random bytes from TPM: "
+ << GetErrorString(result);
+ return false;
+ }
+ if (num_bytes != random_data.size()) {
+ LOG(ERROR) << "Error not enough random bytes received.";
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::SignTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ std::string key_authorization("sign");
+ std::string key_blob;
+ TPM_RC result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001,
+ key_authorization, "", false, // use_only_policy_authorization
+ kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating signing key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE signing_key;
+ result = utility->LoadKey(key_blob, session->GetDelegate(), &signing_key);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading signing key: " << GetErrorString(result);
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), signing_key);
+ session->SetEntityAuthorizationValue(key_authorization);
+ std::string signature;
+ result = utility->Sign(signing_key, TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 'a'), session->GetDelegate(),
+ &signature);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
+ return false;
+ }
+ result = utility->Verify(signing_key, TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 'a'), signature, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to verify: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::DecryptTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ std::string key_authorization("decrypt");
+ std::string key_blob;
+ TPM_RC result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001,
+ key_authorization, "", false, // use_only_policy_authorization
+ kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating decrypt key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE decrypt_key;
+ result = utility->LoadKey(key_blob, session->GetDelegate(), &decrypt_key);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading decrypt key: " << GetErrorString(result);
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), decrypt_key);
+ return PerformRSAEncrpytAndDecrpyt(scoped_key.get(),
+ key_authorization,
+ session.get());
+}
+
+bool TrunksClientTest::ImportTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ std::string modulus;
+ std::string prime_factor;
+ GenerateRSAKeyPair(&modulus, &prime_factor, nullptr);
+ std::string key_blob;
+ std::string key_authorization("import");
+ TPM_RC result = utility->ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, modulus, 0x10001,
+ prime_factor, key_authorization, session->GetDelegate(), &key_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error importing key into TPM: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE key_handle;
+ result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading key into TPM: " << GetErrorString(result);
+ return false;
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), key_handle);
+ return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization,
+ session.get());
+}
+
+bool TrunksClientTest::AuthChangeTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ std::string key_authorization("new_pass");
+ std::string key_blob;
+ TPM_RC result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001,
+ "old_pass", "", false, // use_only_policy_authorization
+ kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating change auth key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE key_handle;
+ result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading change auth key: " << GetErrorString(result);
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), key_handle);
+ session->SetEntityAuthorizationValue("old_pass");
+ result = utility->ChangeKeyAuthorizationData(key_handle, key_authorization,
+ session->GetDelegate(),
+ &key_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error changing auth data: " << GetErrorString(result);
+ return false;
+ }
+ session->SetEntityAuthorizationValue("");
+ result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reloading key: " << GetErrorString(result);
+ return false;
+ }
+ scoped_key.reset(key_handle);
+ return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization,
+ session.get());
+}
+
+bool TrunksClientTest::VerifyKeyCreationTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ std::string key_blob;
+ std::string creation_blob;
+ session->SetEntityAuthorizationValue("");
+ TPM_RC result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001,
+ "", "", false, // use_only_policy_authorization
+ kNoCreationPCR, session->GetDelegate(), &key_blob, &creation_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating certify key: " << GetErrorString(result);
+ return false;
+ }
+ std::string alternate_key_blob;
+ result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001,
+ "", "", false, // use_only_policy_authorization
+ kNoCreationPCR, session->GetDelegate(), &alternate_key_blob,
+ nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating alternate key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE key_handle;
+ result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading certify key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE alternate_key_handle;
+ result = utility->LoadKey(alternate_key_blob,
+ session->GetDelegate(),
+ &alternate_key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading alternate key: " << GetErrorString(result);
+ return false;
+ }
+ ScopedKeyHandle certify_key(*factory_.get(), key_handle);
+ ScopedKeyHandle alternate_key(*factory_.get(), alternate_key_handle);
+ result = utility->CertifyCreation(certify_key.get(), creation_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error certifying key: " << GetErrorString(result);
+ return false;
+ }
+ result = utility->CertifyCreation(alternate_key.get(), creation_blob);
+ if (result == TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error alternate key certified with wrong creation data.";
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::SealedDataTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ int pcr_index = 5;
+ std::string policy_digest;
+ TPM_RC result = utility->GetPolicyDigestForPcrValue(pcr_index, "",
+ &policy_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy_digest: " << GetErrorString(result);
+ return false;
+ }
+ std::string data_to_seal("seal_data");
+ std::string sealed_data;
+ result = utility->SealData(data_to_seal, policy_digest,
+ session->GetDelegate(), &sealed_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result);
+ return false;
+ }
+ scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession();
+ result = policy_session->StartUnboundSession(false);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyPCR(pcr_index, "");
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy to pcr value: "
+ << GetErrorString(result);
+ return false;
+ }
+ std::string unsealed_data;
+ result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
+ &unsealed_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
+ return false;
+ }
+ if (data_to_seal != unsealed_data) {
+ LOG(ERROR) << "Error unsealed data from TPM does not match original data.";
+ return false;
+ }
+ result = utility->ExtendPCR(pcr_index, "extend", session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyPCR(pcr_index, "");
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy to pcr value: "
+ << GetErrorString(result);
+ return false;
+ }
+ result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
+ &unsealed_data);
+ if (result == TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error object was unsealed with wrong policy_digest.";
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::PCRTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session.";
+ return false;
+ }
+ // We are using PCR 2 because it is currently not used by ChromeOS.
+ uint32_t pcr_index = 2;
+ std::string extend_data("data");
+ std::string old_data;
+ TPM_RC result = utility->ReadPCR(pcr_index, &old_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
+ return false;
+ }
+ result = utility->ExtendPCR(pcr_index, extend_data, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error extending PCR value: " << GetErrorString(result);
+ return false;
+ }
+ std::string pcr_data;
+ result = utility->ReadPCR(pcr_index, &pcr_data);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
+ return false;
+ }
+ std::string hashed_extend_data = crypto::SHA256HashString(extend_data);
+ std::string expected_pcr_data =
+ crypto::SHA256HashString(old_data + hashed_extend_data);
+ if (pcr_data.compare(expected_pcr_data) != 0) {
+ LOG(ERROR) << "PCR data does not match expected value.";
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::PolicyAuthValueTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<PolicySession> trial_session = factory_->GetTrialSession();
+ TPM_RC result;
+ result = trial_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = trial_session->PolicyAuthValue();
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy to auth value knowledge: "
+ << GetErrorString(result);
+ return false;
+ }
+ std::string policy_digest;
+ result = trial_session->GetDigest(&policy_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return false;
+ }
+ // Now that we have the digest, we can close the trial session and use hmac.
+ trial_session.reset();
+
+ scoped_ptr<HmacSession> hmac_session = factory_->GetHmacSession();
+ result = hmac_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
+ return false;
+ }
+
+ std::string key_blob;
+ result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
+ "password", policy_digest, true, // use_only_policy_authorization
+ kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
+ return false;
+ }
+
+ TPM_HANDLE key_handle;
+ result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
+ return false;
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), key_handle);
+
+ // Now we can reset the hmac_session.
+ hmac_session.reset();
+
+ scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession();
+ result = policy_session->StartUnboundSession(false);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyAuthValue();
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy to auth value knowledge: "
+ << GetErrorString(result);
+ return false;
+ }
+ std::string signature;
+ policy_session->SetEntityAuthorizationValue("password");
+ result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 0), policy_session->GetDelegate(),
+ &signature);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error signing using RSA key: " << GetErrorString(result);
+ return false;
+ }
+ result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 0), signature, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error verifying using RSA key: " << GetErrorString(result);
+ return false;
+ }
+ std::string ciphertext;
+ result = utility->AsymmetricEncrypt(scoped_key.get(), TPM_ALG_NULL,
+ TPM_ALG_NULL, "plaintext",
+ nullptr,
+ &ciphertext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyAuthValue();
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy to auth value knowledge: "
+ << GetErrorString(result);
+ return false;
+ }
+ std::string plaintext;
+ policy_session->SetEntityAuthorizationValue("password");
+ result = utility->AsymmetricDecrypt(scoped_key.get(), TPM_ALG_NULL,
+ TPM_ALG_NULL, ciphertext,
+ policy_session->GetDelegate(),
+ &plaintext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result);
+ return false;
+ }
+ if (plaintext.compare("plaintext") != 0) {
+ LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::PolicyAndTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<PolicySession> trial_session = factory_->GetTrialSession();
+ TPM_RC result;
+ result = trial_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = trial_session->PolicyCommandCode(TPM_CC_Sign);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ uint32_t pcr_index = 2;
+ std::string pcr_value;
+ result = utility->ReadPCR(pcr_index, &pcr_value);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading pcr: " << GetErrorString(result);
+ return false;
+ }
+ std::string pcr_extend_data("extend");
+ std::string next_pcr_value;
+ std::string hashed_extend_data = crypto::SHA256HashString(pcr_extend_data);
+ next_pcr_value = crypto::SHA256HashString(pcr_value + hashed_extend_data);
+
+ result = trial_session->PolicyPCR(pcr_index, next_pcr_value);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string policy_digest;
+ result = trial_session->GetDigest(&policy_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return false;
+ }
+ // Now that we have the digest, we can close the trial session and use hmac.
+ trial_session.reset();
+
+ scoped_ptr<HmacSession> hmac_session = factory_->GetHmacSession();
+ result = hmac_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
+ return false;
+ }
+ std::string key_authorization("password");
+ std::string key_blob;
+ // This key is created with a policy that dictates it can only be used
+ // when pcr 2 remains unchanged, and when the command is TPM2_Sign.
+ result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
+ key_authorization, policy_digest, true, // use_only_policy_authorization
+ kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE key_handle;
+ result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
+ return false;
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), key_handle);
+
+ // Now we can reset the hmac_session.
+ hmac_session.reset();
+
+ scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession();
+ result = policy_session->StartUnboundSession(false);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyCommandCode(TPM_CC_Sign);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyPCR(pcr_index, "");
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string signature;
+ policy_session->SetEntityAuthorizationValue(key_authorization);
+ // Signing with this key when pcr 2 is unchanged fails.
+ result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 'a'), policy_session->GetDelegate(),
+ &signature);
+ if (GetFormatOneError(result) != TPM_RC_POLICY_FAIL) {
+ LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
+ return false;
+ }
+ scoped_ptr<AuthorizationDelegate> delegate =
+ factory_->GetPasswordAuthorization("");
+ result = utility->ExtendPCR(pcr_index, pcr_extend_data, delegate.get());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
+ return false;
+ }
+ // we have to restart the session because we changed the pcr values.
+ result = policy_session->StartUnboundSession(false);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyCommandCode(TPM_CC_Sign);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyPCR(pcr_index, "");
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ policy_session->SetEntityAuthorizationValue(key_authorization);
+ // Signing with this key when pcr 2 is changed succeeds.
+ result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 'a'), policy_session->GetDelegate(),
+ &signature);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
+ return false;
+ }
+ result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 'a'), signature, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to verify: " << GetErrorString(result);
+ return false;
+ }
+ std::string ciphertext;
+ result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
+ "plaintext", nullptr, &ciphertext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyCommandCode(TPM_CC_Sign);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyPCR(pcr_index, "");
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string plaintext;
+ policy_session->SetEntityAuthorizationValue(key_authorization);
+ // This call is not authorized with the policy, because its command code
+ // is not TPM_CC_SIGN. It should fail with TPM_RC_POLICY_CC.
+ result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
+ ciphertext, policy_session->GetDelegate(),
+ &plaintext);
+ if (GetFormatOneError(result) != TPM_RC_POLICY_CC) {
+ LOG(ERROR) << "Error: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::PolicyOrTest() {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<PolicySession> trial_session = factory_->GetTrialSession();
+ TPM_RC result;
+ // Specify a policy that asserts either TPM_CC_RSA_Encrypt or
+ // TPM_CC_RSA_Decrypt. A key created under this policy can only be used
+ // to encrypt or decrypt.
+ result = trial_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = trial_session->PolicyCommandCode(TPM_CC_Sign);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string sign_digest;
+ result = trial_session->GetDigest(&sign_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return false;
+ }
+ result = trial_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ result = trial_session->PolicyCommandCode(TPM_CC_RSA_Decrypt);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string decrypt_digest;
+ result = trial_session->GetDigest(&decrypt_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return false;
+ }
+ std::vector<std::string> digests;
+ digests.push_back(sign_digest);
+ digests.push_back(decrypt_digest);
+ result = trial_session->PolicyOR(digests);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string policy_digest;
+ result = trial_session->GetDigest(&policy_digest);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
+ return false;
+ }
+ // Now that we have the digest, we can close the trial session and use hmac.
+ trial_session.reset();
+
+ scoped_ptr<HmacSession> hmac_session = factory_->GetHmacSession();
+ result = hmac_session->StartUnboundSession(true);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
+ return false;
+ }
+ std::string key_authorization("password");
+ std::string key_blob;
+ // This key is created with a policy that specifies that it can only be used
+ // for encrypt and decrypt operations.
+ result = utility->CreateRSAKeyPair(
+ TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
+ key_authorization, policy_digest, true, // use_only_policy_authorization
+ kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE key_handle;
+ result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
+ return false;
+ }
+ ScopedKeyHandle scoped_key(*factory_.get(), key_handle);
+
+ // Now we can reset the hmac_session.
+ hmac_session.reset();
+
+ scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession();
+ result = policy_session->StartUnboundSession(false);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
+ return false;
+ }
+ std::string ciphertext;
+ result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
+ "plaintext", nullptr, &ciphertext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyCommandCode(TPM_CC_RSA_Decrypt);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyOR(digests);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string plaintext;
+ policy_session->SetEntityAuthorizationValue(key_authorization);
+ // We can freely use the key for decryption.
+ result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
+ ciphertext, policy_session->GetDelegate(),
+ &plaintext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result);
+ return false;
+ }
+ if (plaintext.compare("plaintext") != 0) {
+ LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
+ return false;
+ }
+ result = policy_session->PolicyCommandCode(TPM_CC_Sign);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ result = policy_session->PolicyOR(digests);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
+ return false;
+ }
+ std::string signature;
+ policy_session->SetEntityAuthorizationValue(key_authorization);
+ // However signing with a key only authorized for encrypt/decrypt should
+ // fail with TPM_RC_POLICY_CC.
+ result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
+ std::string(32, 'a'), policy_session->GetDelegate(),
+ &signature);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::NvramTest(const std::string& owner_password) {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ scoped_ptr<HmacSession> session = factory_->GetHmacSession();
+ TPM_RC result = session->StartUnboundSession(true /* enable encryption */);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
+ return false;
+ }
+ uint32_t index = 1;
+ session->SetEntityAuthorizationValue(owner_password);
+ std::string nv_data("nv_data");
+ result = utility->DefineNVSpace(index, nv_data.size(),
+ session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error defining nvram: " << GetErrorString(result);
+ return false;
+ }
+ session->SetEntityAuthorizationValue(owner_password);
+ result = utility->WriteNVSpace(index, 0, nv_data, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error writing nvram: " << GetErrorString(result);
+ return false;
+ }
+ std::string new_nvdata;
+ session->SetEntityAuthorizationValue("");
+ result = utility->ReadNVSpace(index, 0, nv_data.size(),
+ &new_nvdata, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading nvram: " << GetErrorString(result);
+ return false;
+ }
+ if (nv_data.compare(new_nvdata) != 0) {
+ LOG(ERROR) << "NV space had different data than was written.";
+ return false;
+ }
+ session->SetEntityAuthorizationValue(owner_password);
+ result = utility->LockNVSpace(index, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error locking nvram: " << GetErrorString(result);
+ return false;
+ }
+ session->SetEntityAuthorizationValue("");
+ result = utility->ReadNVSpace(index, 0, nv_data.size(),
+ &new_nvdata, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error reading nvram: " << GetErrorString(result);
+ return false;
+ }
+ if (nv_data.compare(new_nvdata) != 0) {
+ LOG(ERROR) << "NV space had different data than was written.";
+ return false;
+ }
+ session->SetEntityAuthorizationValue(owner_password);
+ result = utility->WriteNVSpace(index, 0, nv_data, session->GetDelegate());
+ if (result == TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Wrote nvram after locking: " << GetErrorString(result);
+ return false;
+ }
+ session->SetEntityAuthorizationValue(owner_password);
+ result = utility->DestroyNVSpace(index, session->GetDelegate());
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error destroying nvram: " << GetErrorString(result);
+ return false;
+ }
+ return true;
+}
+
+bool TrunksClientTest::ManyKeysTest() {
+ const size_t kNumKeys = 20;
+ std::vector<std::unique_ptr<ScopedKeyHandle>> key_handles;
+ std::map<TPM_HANDLE, std::string> public_key_map;
+ for (size_t i = 0; i < kNumKeys; ++i) {
+ std::unique_ptr<ScopedKeyHandle> key_handle(new ScopedKeyHandle(*factory_));
+ std::string public_key;
+ if (!LoadSigningKey(key_handle.get(), &public_key)) {
+ LOG(ERROR) << "Error loading key " << i << " into TPM.";
+ }
+ public_key_map[key_handle->get()] = public_key;
+ key_handles.push_back(std::move(key_handle));
+ }
+ CHECK_EQ(key_handles.size(), kNumKeys);
+ CHECK_EQ(public_key_map.size(), kNumKeys);
+ scoped_ptr<AuthorizationDelegate> delegate =
+ factory_->GetPasswordAuthorization("");
+ for (size_t i = 0; i < kNumKeys; ++i) {
+ const ScopedKeyHandle& key_handle = *key_handles[i];
+ const std::string& public_key = public_key_map[key_handle.get()];
+ if (!SignAndVerify(key_handle, public_key, delegate.get())) {
+ LOG(ERROR) << "Error signing with key " << i;
+ }
+ }
+ std::random_shuffle(key_handles.begin(), key_handles.end());
+ for (size_t i = 0; i < kNumKeys; ++i) {
+ const ScopedKeyHandle& key_handle = *key_handles[i];
+ const std::string& public_key = public_key_map[key_handle.get()];
+ if (!SignAndVerify(key_handle, public_key, delegate.get())) {
+ LOG(ERROR) << "Error signing with shuffled key " << i;
+ }
+ }
+ return true;
+}
+
+bool TrunksClientTest::ManySessionsTest() {
+ const size_t kNumSessions = 20;
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ std::vector<std::unique_ptr<HmacSession>> sessions;
+ for (size_t i = 0; i < kNumSessions; ++i) {
+ std::unique_ptr<HmacSession> session(factory_->GetHmacSession().release());
+ TPM_RC result = session->StartUnboundSession(true /* enable encryption */);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error starting hmac session " << i << ": "
+ << GetErrorString(result);
+ return false;
+ }
+ sessions.push_back(std::move(session));
+ }
+ CHECK_EQ(sessions.size(), kNumSessions);
+ ScopedKeyHandle key_handle(*factory_);
+ std::string public_key;
+ if (!LoadSigningKey(&key_handle, &public_key)) {
+ return false;
+ }
+ for (size_t i = 0; i < kNumSessions; ++i) {
+ if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) {
+ LOG(ERROR) << "Error signing with hmac session " << i;
+ }
+ }
+ std::random_shuffle(sessions.begin(), sessions.end());
+ for (size_t i = 0; i < kNumSessions; ++i) {
+ if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) {
+ LOG(ERROR) << "Error signing with shuffled hmac session " << i;
+ }
+ }
+ return true;
+}
+
+bool TrunksClientTest::PerformRSAEncrpytAndDecrpyt(
+ TPM_HANDLE key_handle,
+ const std::string& key_authorization,
+ HmacSession* session) {
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ std::string ciphertext;
+ session->SetEntityAuthorizationValue("");
+ TPM_RC result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL,
+ TPM_ALG_NULL, "plaintext",
+ session->GetDelegate(),
+ &ciphertext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
+ return false;
+ }
+ std::string plaintext;
+ session->SetEntityAuthorizationValue(key_authorization);
+ result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL,
+ TPM_ALG_NULL, ciphertext,
+ session->GetDelegate(), &plaintext);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result);
+ return false;
+ }
+ if (plaintext.compare("plaintext") != 0) {
+ LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
+ return false;
+ }
+ return true;
+}
+
+void TrunksClientTest::GenerateRSAKeyPair(std::string* modulus,
+ std::string* prime_factor,
+ std::string* public_key) {
+ crypto::ScopedRSA rsa(RSA_generate_key(2048, 0x10001, nullptr, nullptr));
+ CHECK(rsa.get());
+ modulus->resize(BN_num_bytes(rsa.get()->n), 0);
+ BN_bn2bin(rsa.get()->n,
+ reinterpret_cast<unsigned char*>(string_as_array(modulus)));
+ prime_factor->resize(BN_num_bytes(rsa.get()->p), 0);
+ BN_bn2bin(rsa.get()->p,
+ reinterpret_cast<unsigned char*>(string_as_array(prime_factor)));
+ if (public_key) {
+ unsigned char* buffer = NULL;
+ int length = i2d_RSAPublicKey(rsa.get(), &buffer);
+ CHECK_GT(length, 0);
+ crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
+ public_key->assign(reinterpret_cast<char*>(buffer), length);
+ }
+}
+
+bool TrunksClientTest::VerifyRSASignature(const std::string& public_key,
+ const std::string& data,
+ const std::string& signature) {
+ auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
+ crypto::ScopedRSA rsa(d2i_RSAPublicKey(nullptr, &asn1_ptr,
+ public_key.size()));
+ CHECK(rsa.get());
+ std::string digest = crypto::SHA256HashString(data);
+ auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data());
+ std::string mutable_signature(signature);
+ unsigned char* signature_buffer =
+ reinterpret_cast<unsigned char*>(string_as_array(&mutable_signature));
+ return (RSA_verify(NID_sha256, digest_buffer, digest.size(),
+ signature_buffer, signature.size(), rsa.get()) == 1);
+}
+
+bool TrunksClientTest::LoadSigningKey(ScopedKeyHandle* key_handle,
+ std::string* public_key) {
+ std::string modulus;
+ std::string prime_factor;
+ GenerateRSAKeyPair(&modulus, &prime_factor, public_key);
+ std::string key_blob;
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ TPM_RC result = utility->ImportRSAKey(
+ TpmUtility::AsymmetricKeyUsage::kSignKey,
+ modulus, 0x10001, prime_factor,
+ "", // password
+ factory_->GetPasswordAuthorization("").get(),
+ &key_blob);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "ImportRSAKey: " << GetErrorString(result);
+ return false;
+ }
+ TPM_HANDLE raw_key_handle;
+ result = utility->LoadKey(key_blob,
+ factory_->GetPasswordAuthorization("").get(),
+ &raw_key_handle);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "LoadKey: " << GetErrorString(result);
+ return false;
+ }
+ key_handle->reset(raw_key_handle);
+ return true;
+}
+
+bool TrunksClientTest::SignAndVerify(const ScopedKeyHandle& key_handle,
+ const std::string& public_key,
+ AuthorizationDelegate* delegate) {
+ std::string signature;
+ std::string data_to_sign("sign_this");
+ scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility();
+ TPM_RC result = utility->Sign(key_handle.get(),
+ TPM_ALG_RSASSA,
+ TPM_ALG_SHA256,
+ data_to_sign,
+ delegate,
+ &signature);
+ if (result != TPM_RC_SUCCESS) {
+ LOG(ERROR) << "Sign: " << GetErrorString(result);
+ return false;
+ }
+ if (!VerifyRSASignature(public_key, data_to_sign, signature)) {
+ LOG(ERROR) << "Signature verification failed.";
+ return false;
+ }
+ return true;
+}
+
+} // namespace trunks
diff --git a/trunks/trunks_client_test.h b/trunks/trunks_client_test.h
new file mode 100644
index 0000000..92f8683
--- /dev/null
+++ b/trunks/trunks_client_test.h
@@ -0,0 +1,147 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_CLIENT_TEST_H_
+#define TRUNKS_TRUNKS_CLIENT_TEST_H_
+
+#include <string>
+
+#include <base/memory/scoped_ptr.h>
+
+#include "trunks/scoped_key_handle.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_factory.h"
+
+namespace trunks {
+
+// This class is used to perform integration tests on the TPM. Each public
+// method defines a different test to perform.
+// NOTE: All these tests require that the TPM be owned, and SRKs exist.
+// Example usage:
+// TrunksClientTest test;
+// CHECK(test.RNGTest());
+// CHECK(test.SimplePolicyTest());
+class TrunksClientTest {
+ public:
+ TrunksClientTest();
+ // Takes ownership of factory.
+ explicit TrunksClientTest(scoped_ptr<TrunksFactory> factory);
+ virtual ~TrunksClientTest();
+
+ // This test verifies that the Random Number Generator on the TPM is working
+ // correctly.
+ bool RNGTest();
+
+ // This test verifies that we can create an unrestricted RSA signing key and
+ // use it to sign arbitrary data.
+ bool SignTest();
+
+ // This test verfifies that we can create an unrestricted RSA decryption key
+ // and use it to encrypt and decrypt arbitrary data.
+ bool DecryptTest();
+
+ // This test verifies that we can import a RSA key into the TPM and use it
+ // to encrypt and decrypt some data.
+ bool ImportTest();
+
+ // This test verifies that we can change a key's authorization data and
+ // still use it to encrypt/decrypt data.
+ bool AuthChangeTest();
+
+ // This test verifies that we can create a key and then confirm that it
+ // was created by the TPM.
+ bool VerifyKeyCreationTest();
+
+ // This test verifies that we can seal a secret to the TPM and access
+ // it later.
+ bool SealedDataTest();
+
+ // This test performs a simple PCR extension and then reads the value in the
+ // PCR to verify if it is correct.
+ // NOTE: PCR banks need to be configured for this test to succeed. Normally
+ // this is done by the platform firmware.
+ bool PCRTest();
+
+ // This test sets up a PolicySession with the PolicyAuthValue assertion.
+ // This policy is then used to create a key and use it to sign/verify and
+ // encrypt/decrypt.
+ bool PolicyAuthValueTest();
+
+ // This test sets up a PolicySession that is based on the current PCR value
+ // and a CommandCode for signing. The key created this way is restricted to
+ // be only used for signing, and only if the PCR remains unchanged. The key
+ // is then used to sign arbitrary data, and the signature verified.
+ bool PolicyAndTest();
+
+ // This test performs a complex assertion using PolicyOR.
+ // We create an unrestricted key, and restricts it to signing
+ // and decryption using Policy Sessions.
+ bool PolicyOrTest();
+
+ // This test verfies that we can create, write, read, lock and delete
+ // NV spaces in the TPM.
+ // NOTE: This test needs the |owner_password| to work.
+ bool NvramTest(const std::string& owner_password);
+
+ // This test uses many key handles simultaneously.
+ bool ManyKeysTest();
+
+ // This test uses many sessions simultaneously.
+ bool ManySessionsTest();
+
+ private:
+ // This method verifies that plaintext == decrypt(encrypt(plaintext)) using
+ // a given key.
+ // TODO(usanghi): Remove |session| argument once we can support multiple
+ // sessions.
+ bool PerformRSAEncrpytAndDecrpyt(TPM_HANDLE key_handle,
+ const std::string& key_authorization,
+ HmacSession* session);
+
+ // Generates an RSA key pair in software. The |modulus| and |prime_factor|
+ // must not be NULL and will be populated with values that can be imported
+ // into the TPM. The |public_key| may be NULL, but if it is not, will be
+ // populated with a value that can be used with VerifyRSASignature.
+ void GenerateRSAKeyPair(std::string* modulus,
+ std::string* prime_factor,
+ std::string* public_key);
+
+ // Verifies an RSA-SSA-SHA256 |signature| over the given |data|. The
+ // |public_key| is as produced by GenerateRSAKeyPair(). Returns true on
+ // success.
+ bool VerifyRSASignature(const std::string& public_key,
+ const std::string& data,
+ const std::string& signature);
+
+ // Loads an arbitrary RSA signing key and provides the |key_handle| and the
+ // |public_key|. Returns true on success.
+ bool LoadSigningKey(ScopedKeyHandle* key_handle, std::string* public_key);
+
+ // Signs arbitrary data with |key_handle| authorized by |delegate| and
+ // verifies the signature with |public_key|. Returns true on success.
+ bool SignAndVerify(const ScopedKeyHandle& key_handle,
+ const std::string& public_key,
+ AuthorizationDelegate* delegate);
+
+ // Factory for instantiation of Tpm classes
+ scoped_ptr<TrunksFactory> factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksClientTest);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TRUNKS_CLIENT_TEST_H_
diff --git a/trunks/trunks_export.h b/trunks/trunks_export.h
new file mode 100644
index 0000000..967b4b3
--- /dev/null
+++ b/trunks/trunks_export.h
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_EXPORT_H_
+#define TRUNKS_TRUNKS_EXPORT_H_
+
+// Use this for any class or function that needs to be exported from libtrunks.
+// E.g. TRUNKS_EXPORT void foo();
+#define TRUNKS_EXPORT __attribute__((__visibility__("default")))
+
+#endif // TRUNKS_TRUNKS_EXPORT_H_
diff --git a/trunks/trunks_factory.h b/trunks/trunks_factory.h
new file mode 100644
index 0000000..b90baa6
--- /dev/null
+++ b/trunks/trunks_factory.h
@@ -0,0 +1,81 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_FACTORY_H_
+#define TRUNKS_TRUNKS_FACTORY_H_
+
+#include <string>
+
+#include <base/macros.h>
+#include <base/memory/scoped_ptr.h>
+
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class AuthorizationDelegate;
+class BlobParser;
+class HmacSession;
+class PolicySession;
+class SessionManager;
+class Tpm;
+class TpmState;
+class TpmUtility;
+
+// TrunksFactory is an interface to act as a factory for trunks objects. This
+// mechanism assists in injecting mocks for testing. This class is not
+// thread-safe.
+class TRUNKS_EXPORT TrunksFactory {
+ public:
+ TrunksFactory() {}
+ virtual ~TrunksFactory() {}
+
+ // Returns a Tpm instance. The caller does not take ownership.
+ virtual Tpm* GetTpm() const = 0;
+
+ // Returns an uninitialized TpmState instance. The caller takes ownership.
+ virtual scoped_ptr<TpmState> GetTpmState() const = 0;
+
+ // Returns a TpmUtility instance. The caller takes ownership.
+ virtual scoped_ptr<TpmUtility> GetTpmUtility() const = 0;
+
+ // Returns an AuthorizationDelegate instance for basic password authorization.
+ // The caller takes ownership.
+ virtual scoped_ptr<AuthorizationDelegate> GetPasswordAuthorization(
+ const std::string& password) const = 0;
+
+ // Returns a SessionManager instance. The caller takes ownership.
+ virtual scoped_ptr<SessionManager> GetSessionManager() const = 0;
+
+ // Returns a HmacSession instance. The caller takes ownership.
+ virtual scoped_ptr<HmacSession> GetHmacSession() const = 0;
+
+ // Returns a PolicySession instance. The caller takes ownership.
+ virtual scoped_ptr<PolicySession> GetPolicySession() const = 0;
+
+ // Returns a TrialSession instance. The caller takes ownership.
+ virtual scoped_ptr<PolicySession> GetTrialSession() const = 0;
+
+ // Returns a BlobParser instance. The caller takes ownership.
+ virtual scoped_ptr<BlobParser> GetBlobParser() const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TrunksFactory);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TRUNKS_FACTORY_H_
diff --git a/trunks/trunks_factory_for_test.cc b/trunks/trunks_factory_for_test.cc
new file mode 100644
index 0000000..6b73e64
--- /dev/null
+++ b/trunks/trunks_factory_for_test.cc
@@ -0,0 +1,599 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/trunks_factory_for_test.h"
+
+#include <gmock/gmock.h>
+
+#include "trunks/authorization_delegate.h"
+#include "trunks/blob_parser.h"
+#include "trunks/hmac_session.h"
+#include "trunks/mock_blob_parser.h"
+#include "trunks/mock_hmac_session.h"
+#include "trunks/mock_policy_session.h"
+#include "trunks/mock_session_manager.h"
+#include "trunks/mock_tpm.h"
+#include "trunks/mock_tpm_state.h"
+#include "trunks/mock_tpm_utility.h"
+#include "trunks/policy_session.h"
+#include "trunks/session_manager.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/tpm_state.h"
+#include "trunks/tpm_utility.h"
+
+using testing::NiceMock;
+
+namespace trunks {
+
+// Forwards all calls to a target instance.
+class TpmStateForwarder : public TpmState {
+ public:
+ explicit TpmStateForwarder(TpmState* target) : target_(target) {}
+ ~TpmStateForwarder() override = default;
+
+ TPM_RC Initialize() override {
+ return target_->Initialize();
+ }
+
+ bool IsOwnerPasswordSet() override {
+ return target_->IsOwnerPasswordSet();
+ }
+
+ bool IsEndorsementPasswordSet() override {
+ return target_->IsEndorsementPasswordSet();
+ }
+
+ bool IsLockoutPasswordSet() override {
+ return target_->IsLockoutPasswordSet();
+ }
+
+ bool IsOwned() override {
+ return target_->IsOwned();
+ }
+
+ bool IsInLockout() override {
+ return target_->IsInLockout();
+ }
+
+ bool IsPlatformHierarchyEnabled() override {
+ return target_->IsPlatformHierarchyEnabled();
+ }
+
+ bool IsStorageHierarchyEnabled() override {
+ return target_->IsStorageHierarchyEnabled();
+ }
+
+ bool IsEndorsementHierarchyEnabled() override {
+ return target_->IsEndorsementHierarchyEnabled();
+ }
+
+ bool IsEnabled() override {
+ return target_->IsEnabled();
+ }
+
+ bool WasShutdownOrderly() override {
+ return target_->WasShutdownOrderly();
+ }
+
+ bool IsRSASupported() override {
+ return target_->IsRSASupported();
+ }
+
+ bool IsECCSupported() override {
+ return target_->IsECCSupported();
+ }
+
+ uint32_t GetLockoutCounter() override {
+ return target_->GetLockoutCounter();
+ }
+
+ uint32_t GetLockoutThreshold() override {
+ return target_->GetLockoutThreshold();
+ }
+
+ uint32_t GetLockoutInterval() override {
+ return target_->GetLockoutInterval();
+ }
+
+ uint32_t GetLockoutRecovery() override {
+ return target_->GetLockoutRecovery();
+ }
+
+ private:
+ TpmState* target_;
+};
+
+// Forwards all calls to a target instance.
+class TpmUtilityForwarder : public TpmUtility {
+ public:
+ explicit TpmUtilityForwarder(TpmUtility* target) : target_(target) {}
+ ~TpmUtilityForwarder() override = default;
+
+ TPM_RC Startup() override {
+ return target_->Startup();
+ }
+
+ TPM_RC Clear() override {
+ return target_->Clear();
+ }
+
+ void Shutdown() override {
+ return target_->Shutdown();
+ }
+
+ TPM_RC InitializeTpm() override {
+ return target_->InitializeTpm();
+ }
+
+ TPM_RC AllocatePCR(const std::string& platform_password) override {
+ return target_->AllocatePCR(platform_password);
+ }
+
+ TPM_RC TakeOwnership(const std::string& owner_password,
+ const std::string& endorsement_password,
+ const std::string& lockout_password) override {
+ return target_->TakeOwnership(owner_password,
+ endorsement_password,
+ lockout_password);
+ }
+
+ TPM_RC StirRandom(const std::string& entropy_data,
+ AuthorizationDelegate* delegate) override {
+ return target_->StirRandom(entropy_data, delegate);
+ }
+
+ TPM_RC GenerateRandom(size_t num_bytes,
+ AuthorizationDelegate* delegate,
+ std::string* random_data) override {
+ return target_->GenerateRandom(num_bytes, delegate, random_data);
+ }
+
+ TPM_RC ExtendPCR(int pcr_index,
+ const std::string& extend_data,
+ AuthorizationDelegate* delegate) override {
+ return target_->ExtendPCR(pcr_index, extend_data, delegate);
+ }
+
+ TPM_RC ReadPCR(int pcr_index, std::string* pcr_value) override {
+ return target_->ReadPCR(pcr_index, pcr_value);
+ }
+
+ TPM_RC AsymmetricEncrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* ciphertext) override {
+ return target_->AsymmetricEncrypt(key_handle,
+ scheme,
+ hash_alg,
+ plaintext,
+ delegate,
+ ciphertext);
+ }
+
+ TPM_RC AsymmetricDecrypt(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& ciphertext,
+ AuthorizationDelegate* delegate,
+ std::string* plaintext) override {
+ return target_->AsymmetricDecrypt(key_handle,
+ scheme,
+ hash_alg,
+ ciphertext,
+ delegate,
+ plaintext);
+ }
+
+ TPM_RC Sign(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ AuthorizationDelegate* delegate,
+ std::string* signature) override {
+ return target_->Sign(key_handle,
+ scheme,
+ hash_alg,
+ plaintext,
+ delegate,
+ signature);
+ }
+
+ TPM_RC Verify(TPM_HANDLE key_handle,
+ TPM_ALG_ID scheme,
+ TPM_ALG_ID hash_alg,
+ const std::string& plaintext,
+ const std::string& signature,
+ AuthorizationDelegate* delegate) override {
+ return target_->Verify(key_handle, scheme, hash_alg,
+ plaintext, signature, delegate);
+ }
+
+ TPM_RC CertifyCreation(TPM_HANDLE key_handle,
+ const std::string& creation_blob) override {
+ return target_->CertifyCreation(key_handle, creation_blob);
+ }
+
+ TPM_RC ChangeKeyAuthorizationData(TPM_HANDLE key_handle,
+ const std::string& new_password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) override {
+ return target_->ChangeKeyAuthorizationData(key_handle,
+ new_password,
+ delegate,
+ key_blob);
+ }
+
+ TPM_RC ImportRSAKey(AsymmetricKeyUsage key_type,
+ const std::string& modulus,
+ uint32_t public_exponent,
+ const std::string& prime_factor,
+ const std::string& password,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob) override {
+ return target_->ImportRSAKey(key_type, modulus, public_exponent,
+ prime_factor, password, delegate, key_blob);
+ }
+
+ TPM_RC CreateRSAKeyPair(AsymmetricKeyUsage key_type,
+ int modulus_bits,
+ uint32_t public_exponent,
+ const std::string& password,
+ const std::string& policy_digest,
+ bool use_only_policy_authorization,
+ int creation_pcr_index,
+ AuthorizationDelegate* delegate,
+ std::string* key_blob,
+ std::string* creation_blob) override {
+ return target_->CreateRSAKeyPair(key_type, modulus_bits, public_exponent,
+ password, policy_digest,
+ use_only_policy_authorization,
+ creation_pcr_index,
+ delegate, key_blob, creation_blob);
+ }
+
+ TPM_RC LoadKey(const std::string& key_blob,
+ AuthorizationDelegate* delegate,
+ TPM_HANDLE* key_handle) override {
+ return target_->LoadKey(key_blob, delegate, key_handle);
+ }
+
+ TPM_RC GetKeyName(TPM_HANDLE handle, std::string* name) override {
+ return target_->GetKeyName(handle, name);
+ }
+
+ TPM_RC GetKeyPublicArea(TPM_HANDLE handle,
+ TPMT_PUBLIC* public_data) override {
+ return target_->GetKeyPublicArea(handle, public_data);
+ }
+
+ TPM_RC SealData(const std::string& data_to_seal,
+ const std::string& policy_digest,
+ AuthorizationDelegate* delegate,
+ std::string* sealed_data) override {
+ return target_->SealData(data_to_seal, policy_digest,
+ delegate, sealed_data);
+ }
+
+ TPM_RC UnsealData(const std::string& sealed_data,
+ AuthorizationDelegate* delegate,
+ std::string* unsealed_data) override {
+ return target_->UnsealData(sealed_data, delegate, unsealed_data);
+ }
+
+ TPM_RC StartSession(HmacSession* session) override {
+ return target_->StartSession(session);
+ }
+
+ TPM_RC GetPolicyDigestForPcrValue(int pcr_index,
+ const std::string& pcr_value,
+ std::string* policy_digest) override {
+ return target_->GetPolicyDigestForPcrValue(pcr_index, pcr_value,
+ policy_digest);
+ }
+
+ TPM_RC DefineNVSpace(uint32_t index,
+ size_t num_bytes,
+ AuthorizationDelegate* delegate) override {
+ return target_->DefineNVSpace(index, num_bytes, delegate);
+ }
+
+ TPM_RC DestroyNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) override {
+ return target_->DestroyNVSpace(index, delegate);
+ }
+
+ TPM_RC LockNVSpace(uint32_t index,
+ AuthorizationDelegate* delegate) override {
+ return target_->LockNVSpace(index, delegate);
+ }
+
+ TPM_RC WriteNVSpace(uint32_t index,
+ uint32_t offset,
+ const std::string& nvram_data,
+ AuthorizationDelegate* delegate) override {
+ return target_->WriteNVSpace(index, offset, nvram_data, delegate);
+ }
+
+ TPM_RC ReadNVSpace(uint32_t index,
+ uint32_t offset,
+ size_t num_bytes,
+ std::string* nvram_data,
+ AuthorizationDelegate* delegate) override {
+ return target_->ReadNVSpace(index, offset, num_bytes, nvram_data, delegate);
+ }
+
+ TPM_RC GetNVSpaceName(uint32_t index, std::string* name) override {
+ return target_->GetNVSpaceName(index, name);
+ }
+
+ TPM_RC GetNVSpacePublicArea(uint32_t index,
+ TPMS_NV_PUBLIC* public_data) override {
+ return target_->GetNVSpacePublicArea(index, public_data);
+ }
+
+ private:
+ TpmUtility* target_;
+};
+
+// Forwards all calls to a target instance.
+class AuthorizationDelegateForwarder : public AuthorizationDelegate {
+ public:
+ explicit AuthorizationDelegateForwarder(AuthorizationDelegate* target)
+ : target_(target) {}
+ ~AuthorizationDelegateForwarder() override = default;
+
+ bool GetCommandAuthorization(const std::string& command_hash,
+ bool is_command_parameter_encryption_possible,
+ bool is_response_parameter_encryption_possible,
+ std::string* authorization) override {
+ return target_->GetCommandAuthorization(
+ command_hash,
+ is_command_parameter_encryption_possible,
+ is_response_parameter_encryption_possible,
+ authorization);
+ }
+
+ bool CheckResponseAuthorization(const std::string& response_hash,
+ const std::string& authorization) override {
+ return target_->CheckResponseAuthorization(response_hash, authorization);
+ }
+
+ bool EncryptCommandParameter(std::string* parameter) override {
+ return target_->EncryptCommandParameter(parameter);
+ }
+
+ bool DecryptResponseParameter(std::string* parameter) override {
+ return target_->DecryptResponseParameter(parameter);
+ }
+
+ private:
+ AuthorizationDelegate* target_;
+};
+
+// Forwards all calls to a target instance.
+class SessionManagerForwarder : public SessionManager {
+ public:
+ explicit SessionManagerForwarder(SessionManager* target) : target_(target) {}
+ ~SessionManagerForwarder() override {}
+
+ TPM_HANDLE GetSessionHandle() const override {
+ return target_->GetSessionHandle();
+ }
+
+ void CloseSession() override {
+ return target_->CloseSession();
+ }
+
+ TPM_RC StartSession(TPM_SE session_type, TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption,
+ HmacAuthorizationDelegate* delegate) override {
+ return target_->StartSession(session_type, bind_entity,
+ bind_authorization_value,
+ enable_encryption, delegate);
+ }
+
+ private:
+ SessionManager* target_;
+};
+
+// Forwards all calls to a target instance.
+class HmacSessionForwarder : public HmacSession {
+ public:
+ explicit HmacSessionForwarder(HmacSession* target): target_(target) {}
+ ~HmacSessionForwarder() override = default;
+
+ AuthorizationDelegate* GetDelegate() override {
+ return target_->GetDelegate();
+ }
+
+ TPM_RC StartBoundSession(TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) override {
+ return target_->StartBoundSession(bind_entity,
+ bind_authorization_value,
+ enable_encryption);
+ }
+
+ TPM_RC StartUnboundSession(bool enable_encryption) override {
+ return target_->StartUnboundSession(enable_encryption);
+ }
+
+ void SetEntityAuthorizationValue(const std::string& value) override {
+ return target_->SetEntityAuthorizationValue(value);
+ }
+
+ void SetFutureAuthorizationValue(const std::string& value) override {
+ return target_->SetFutureAuthorizationValue(value);
+ }
+
+ private:
+ HmacSession* target_;
+};
+
+
+// Forwards all calls to a target instance.
+class PolicySessionForwarder : public PolicySession {
+ public:
+ explicit PolicySessionForwarder(PolicySession* target): target_(target) {}
+ ~PolicySessionForwarder() override = default;
+
+ AuthorizationDelegate* GetDelegate() override {
+ return target_->GetDelegate();
+ }
+
+ TPM_RC StartBoundSession(TPMI_DH_ENTITY bind_entity,
+ const std::string& bind_authorization_value,
+ bool enable_encryption) override {
+ return target_->StartBoundSession(bind_entity,
+ bind_authorization_value,
+ enable_encryption);
+ }
+
+ TPM_RC StartUnboundSession(bool enable_encryption) override {
+ return target_->StartUnboundSession(enable_encryption);
+ }
+
+ TPM_RC GetDigest(std::string* digest) override {
+ return target_->GetDigest(digest);
+ }
+
+ TPM_RC PolicyOR(const std::vector<std::string>& digests) override {
+ return target_->PolicyOR(digests);
+ }
+
+ TPM_RC PolicyPCR(uint32_t pcr_index, const std::string& pcr_value) override {
+ return target_->PolicyPCR(pcr_index, pcr_value);
+ }
+
+ TPM_RC PolicyCommandCode(TPM_CC command_code) override {
+ return target_->PolicyCommandCode(command_code);
+ }
+
+ TPM_RC PolicyAuthValue() override {
+ return target_->PolicyAuthValue();
+ }
+
+ void SetEntityAuthorizationValue(const std::string& value) override {
+ return target_->SetEntityAuthorizationValue(value);
+ }
+
+ private:
+ PolicySession* target_;
+};
+
+// Forwards all calls to a target instance.
+class BlobParserForwarder : public BlobParser {
+ public:
+ explicit BlobParserForwarder(BlobParser* target): target_(target) {}
+ ~BlobParserForwarder() override = default;
+
+ bool SerializeKeyBlob(const TPM2B_PUBLIC& public_info,
+ const TPM2B_PRIVATE& private_info,
+ std::string* key_blob) override {
+ return target_->SerializeKeyBlob(public_info, private_info, key_blob);
+ }
+
+ bool ParseKeyBlob(const std::string& key_blob,
+ TPM2B_PUBLIC* public_info,
+ TPM2B_PRIVATE* private_info) override {
+ return target_->ParseKeyBlob(key_blob, public_info, private_info);
+ }
+
+ bool SerializeCreationBlob(const TPM2B_CREATION_DATA& creation_data,
+ const TPM2B_DIGEST& creation_hash,
+ const TPMT_TK_CREATION& creation_ticket,
+ std::string* creation_blob) override {
+ return target_->SerializeCreationBlob(creation_data, creation_hash,
+ creation_ticket, creation_blob);
+ }
+
+ bool ParseCreationBlob(const std::string& creation_blob,
+ TPM2B_CREATION_DATA* creation_data,
+ TPM2B_DIGEST* creation_hash,
+ TPMT_TK_CREATION* creation_ticket) override {
+ return target_->ParseCreationBlob(creation_blob, creation_data,
+ creation_hash, creation_ticket);
+ }
+
+ private:
+ BlobParser* target_;
+};
+
+TrunksFactoryForTest::TrunksFactoryForTest()
+ : default_tpm_(new NiceMock<MockTpm>()),
+ tpm_(default_tpm_.get()),
+ default_tpm_state_(new NiceMock<MockTpmState>()),
+ tpm_state_(default_tpm_state_.get()),
+ default_tpm_utility_(new NiceMock<MockTpmUtility>()),
+ tpm_utility_(default_tpm_utility_.get()),
+ default_authorization_delegate_(new PasswordAuthorizationDelegate("")),
+ password_authorization_delegate_(default_authorization_delegate_.get()),
+ default_session_manager_(new NiceMock<MockSessionManager>()),
+ session_manager_(default_session_manager_.get()),
+ default_hmac_session_(new NiceMock<MockHmacSession>()),
+ hmac_session_(default_hmac_session_.get()),
+ default_policy_session_(new NiceMock<MockPolicySession>()),
+ policy_session_(default_policy_session_.get()),
+ default_blob_parser_(new NiceMock<MockBlobParser>()),
+ blob_parser_(default_blob_parser_.get()) {
+}
+
+TrunksFactoryForTest::~TrunksFactoryForTest() {}
+
+Tpm* TrunksFactoryForTest::GetTpm() const {
+ return tpm_;
+}
+
+scoped_ptr<TpmState> TrunksFactoryForTest::GetTpmState() const {
+ return scoped_ptr<TpmState>(new TpmStateForwarder(tpm_state_));
+}
+
+scoped_ptr<TpmUtility> TrunksFactoryForTest::GetTpmUtility() const {
+ return scoped_ptr<TpmUtility>(new TpmUtilityForwarder(tpm_utility_));
+}
+
+scoped_ptr<AuthorizationDelegate>
+ TrunksFactoryForTest::GetPasswordAuthorization(
+ const std::string& password) const {
+ return scoped_ptr<AuthorizationDelegate>(
+ new AuthorizationDelegateForwarder(password_authorization_delegate_));
+}
+
+scoped_ptr<SessionManager> TrunksFactoryForTest::GetSessionManager() const {
+ return scoped_ptr<SessionManager>(
+ new SessionManagerForwarder(session_manager_));
+}
+
+scoped_ptr<HmacSession> TrunksFactoryForTest::GetHmacSession() const {
+ return scoped_ptr<HmacSession>(new HmacSessionForwarder(hmac_session_));
+}
+
+scoped_ptr<PolicySession> TrunksFactoryForTest::GetPolicySession() const {
+ return scoped_ptr<PolicySession>(new PolicySessionForwarder(policy_session_));
+}
+
+scoped_ptr<PolicySession> TrunksFactoryForTest::GetTrialSession() const {
+ return scoped_ptr<PolicySession>(new PolicySessionForwarder(policy_session_));
+}
+
+scoped_ptr<BlobParser> TrunksFactoryForTest::GetBlobParser() const {
+ return scoped_ptr<BlobParser>(new BlobParserForwarder(blob_parser_));
+}
+
+} // namespace trunks
diff --git a/trunks/trunks_factory_for_test.h b/trunks/trunks_factory_for_test.h
new file mode 100644
index 0000000..190326e
--- /dev/null
+++ b/trunks/trunks_factory_for_test.h
@@ -0,0 +1,131 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_FACTORY_FOR_TEST_H_
+#define TRUNKS_TRUNKS_FACTORY_FOR_TEST_H_
+
+#include "trunks/trunks_factory.h"
+
+#include <string>
+
+#include <base/macros.h>
+#include <base/memory/scoped_ptr.h>
+
+#include "trunks/password_authorization_delegate.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class AuthorizationDelegate;
+class MockBlobParser;
+class MockHmacSession;
+class MockPolicySession;
+class MockSessionManager;
+class MockTpm;
+class MockTpmState;
+class MockTpmUtility;
+class HmacSession;
+class PasswordAuthorizationDelegate;
+class PolicySession;
+class SessionManager;
+class Tpm;
+class TpmState;
+class TpmUtility;
+
+// A factory implementation for testing. Custom instances can be injected. If no
+// instance has been injected, a default mock instance will be used. Objects for
+// which ownership is passed to the caller are instantiated as forwarders which
+// simply forward calls to the current instance set for the class.
+//
+// Example usage:
+// TrunksFactoryForTest factory;
+// MockTpmState mock_tpm_state;
+// factory.set_tpm_state(mock_tpm_state);
+// // Set expectations on mock_tpm_state...
+class TRUNKS_EXPORT TrunksFactoryForTest : public TrunksFactory {
+ public:
+ TrunksFactoryForTest();
+ ~TrunksFactoryForTest() override;
+
+ // TrunksFactory methods.
+ Tpm* GetTpm() const override;
+ scoped_ptr<TpmState> GetTpmState() const override;
+ scoped_ptr<TpmUtility> GetTpmUtility() const override;
+ scoped_ptr<AuthorizationDelegate> GetPasswordAuthorization(
+ const std::string& password) const override;
+ scoped_ptr<SessionManager> GetSessionManager() const override;
+ scoped_ptr<HmacSession> GetHmacSession() const override;
+ scoped_ptr<PolicySession> GetPolicySession() const override;
+ scoped_ptr<PolicySession> GetTrialSession() const override;
+ scoped_ptr<BlobParser> GetBlobParser() const override;
+
+ // Mutators to inject custom mocks.
+ void set_tpm(Tpm* tpm) {
+ tpm_ = tpm;
+ }
+
+ void set_tpm_state(TpmState* tpm_state) {
+ tpm_state_ = tpm_state;
+ }
+
+ void set_tpm_utility(TpmUtility* tpm_utility) {
+ tpm_utility_ = tpm_utility;
+ }
+
+ void set_password_authorization_delegate(AuthorizationDelegate* delegate) {
+ password_authorization_delegate_ = delegate;
+ }
+
+ void set_session_manager(SessionManager* session_manager) {
+ session_manager_ = session_manager;
+ }
+
+ void set_hmac_session(HmacSession* hmac_session) {
+ hmac_session_ = hmac_session;
+ }
+
+ void set_policy_session(PolicySession* policy_session) {
+ policy_session_ = policy_session;
+ }
+
+ void set_blob_parser(BlobParser* blob_parser) {
+ blob_parser_ = blob_parser;
+ }
+
+ private:
+ scoped_ptr<MockTpm> default_tpm_;
+ Tpm* tpm_;
+ scoped_ptr<MockTpmState> default_tpm_state_;
+ TpmState* tpm_state_;
+ scoped_ptr<MockTpmUtility> default_tpm_utility_;
+ TpmUtility* tpm_utility_;
+ scoped_ptr<PasswordAuthorizationDelegate> default_authorization_delegate_;
+ AuthorizationDelegate* password_authorization_delegate_;
+ scoped_ptr<MockSessionManager> default_session_manager_;
+ SessionManager* session_manager_;
+ scoped_ptr<MockHmacSession> default_hmac_session_;
+ HmacSession* hmac_session_;
+ scoped_ptr<MockPolicySession> default_policy_session_;
+ PolicySession* policy_session_;
+ scoped_ptr<MockBlobParser> default_blob_parser_;
+ BlobParser* blob_parser_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksFactoryForTest);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TRUNKS_FACTORY_FOR_TEST_H_
diff --git a/trunks/trunks_factory_impl.cc b/trunks/trunks_factory_impl.cc
new file mode 100644
index 0000000..935aba8
--- /dev/null
+++ b/trunks/trunks_factory_impl.cc
@@ -0,0 +1,85 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/trunks_factory_impl.h"
+
+#include "trunks/blob_parser.h"
+#include "trunks/hmac_session_impl.h"
+#include "trunks/password_authorization_delegate.h"
+#include "trunks/policy_session_impl.h"
+#include "trunks/session_manager_impl.h"
+#include "trunks/tpm_generated.h"
+#include "trunks/tpm_state_impl.h"
+#include "trunks/tpm_utility_impl.h"
+#include "trunks/trunks_proxy.h"
+
+namespace trunks {
+
+TrunksFactoryImpl::TrunksFactoryImpl() {
+ default_transceiver_.reset(new TrunksProxy());
+ transceiver_ = default_transceiver_.get();
+ tpm_.reset(new Tpm(transceiver_));
+ if (!transceiver_->Init()) {
+ LOG(ERROR) << "Error initializing transceiver.";
+ }
+}
+
+TrunksFactoryImpl::TrunksFactoryImpl(CommandTransceiver* transceiver) {
+ transceiver_ = transceiver;
+ tpm_.reset(new Tpm(transceiver_));
+}
+
+TrunksFactoryImpl::~TrunksFactoryImpl() {}
+
+Tpm* TrunksFactoryImpl::GetTpm() const {
+ return tpm_.get();
+}
+
+scoped_ptr<TpmState> TrunksFactoryImpl::GetTpmState() const {
+ return scoped_ptr<TpmState>(new TpmStateImpl(*this));
+}
+
+scoped_ptr<TpmUtility> TrunksFactoryImpl::GetTpmUtility() const {
+ return scoped_ptr<TpmUtility>(new TpmUtilityImpl(*this));
+}
+
+scoped_ptr<AuthorizationDelegate> TrunksFactoryImpl::GetPasswordAuthorization(
+ const std::string& password) const {
+ return scoped_ptr<AuthorizationDelegate>(
+ new PasswordAuthorizationDelegate(password));
+}
+
+scoped_ptr<SessionManager> TrunksFactoryImpl::GetSessionManager() const {
+ return scoped_ptr<SessionManager>(new SessionManagerImpl(*this));
+}
+
+scoped_ptr<HmacSession> TrunksFactoryImpl::GetHmacSession() const {
+ return scoped_ptr<HmacSession>(new HmacSessionImpl(*this));
+}
+
+scoped_ptr<PolicySession> TrunksFactoryImpl::GetPolicySession() const {
+ return scoped_ptr<PolicySession>(new PolicySessionImpl(*this, TPM_SE_POLICY));
+}
+
+scoped_ptr<PolicySession> TrunksFactoryImpl::GetTrialSession() const {
+ return scoped_ptr<PolicySession>(new PolicySessionImpl(*this, TPM_SE_TRIAL));
+}
+
+scoped_ptr<BlobParser> TrunksFactoryImpl::GetBlobParser() const {
+ return scoped_ptr<BlobParser>(new BlobParser());
+}
+
+} // namespace trunks
diff --git a/trunks/trunks_factory_impl.h b/trunks/trunks_factory_impl.h
new file mode 100644
index 0000000..084aab7
--- /dev/null
+++ b/trunks/trunks_factory_impl.h
@@ -0,0 +1,68 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_FACTORY_IMPL_H_
+#define TRUNKS_TRUNKS_FACTORY_IMPL_H_
+
+#include "trunks/trunks_factory.h"
+
+#include <string>
+
+#include <base/macros.h>
+#include <base/memory/scoped_ptr.h>
+
+#include "trunks/command_transceiver.h"
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+class Tpm;
+class TrunksProxy;
+
+// TrunksFactoryImpl is the default TrunksFactory implementation.
+class TRUNKS_EXPORT TrunksFactoryImpl : public TrunksFactory {
+ public:
+ // Uses TrunksProxy as the default CommandTransceiver to pass to the TPM.
+ TrunksFactoryImpl();
+ // TrunksFactoryImpl does not take ownership of |transceiver|. This
+ // transceiver is forwarded down to the Tpm instance maintained by
+ // this factory.
+ explicit TrunksFactoryImpl(CommandTransceiver* transceiver);
+ ~TrunksFactoryImpl() override;
+
+ // TrunksFactory methods.
+ Tpm* GetTpm() const override;
+ scoped_ptr<TpmState> GetTpmState() const override;
+ scoped_ptr<TpmUtility> GetTpmUtility() const override;
+ scoped_ptr<AuthorizationDelegate> GetPasswordAuthorization(
+ const std::string& password) const override;
+ scoped_ptr<SessionManager> GetSessionManager() const override;
+ scoped_ptr<HmacSession> GetHmacSession() const override;
+ scoped_ptr<PolicySession> GetPolicySession() const override;
+ scoped_ptr<PolicySession> GetTrialSession() const override;
+ scoped_ptr<BlobParser> GetBlobParser() const override;
+
+ private:
+ scoped_ptr<CommandTransceiver> default_transceiver_;
+ CommandTransceiver* transceiver_;
+ scoped_ptr<Tpm> tpm_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksFactoryImpl);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TRUNKS_FACTORY_IMPL_H_
diff --git a/trunks/trunks_ftdi_spi.cc b/trunks/trunks_ftdi_spi.cc
new file mode 100644
index 0000000..8a6de59
--- /dev/null
+++ b/trunks/trunks_ftdi_spi.cc
@@ -0,0 +1,344 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#include <algorithm>
+#include <ctime>
+#include <string>
+#include <unistd.h>
+
+#include <base/logging.h>
+
+#include "trunks/tpm_generated.h"
+#include "trunks/trunks_ftdi_spi.h"
+
+// Assorted TPM2 registers for interface type FIFO.
+#define TPM_ACCESS_REG 0
+#define TPM_STS_REG 0x18
+#define TPM_DATA_FIFO_REG 0x24
+#define TPM_DID_VID_REG 0xf00
+#define TPM_RID_REG 0xf04
+
+namespace trunks {
+
+// Locality management bits (in TPM_ACCESS_REG)
+enum TpmAccessBits {
+ tpmRegValidSts = (1 << 7),
+ activeLocality = (1 << 5),
+ requestUse = (1 << 1),
+ tpmEstablishment = (1 << 0),
+};
+
+enum TpmStsBits {
+ tpmFamilyShift = 26,
+ tpmFamilyMask = ((1 << 2) - 1), // 2 bits wide
+ tpmFamilyTPM2 = 1,
+ resetEstablishmentBit = (1 << 25),
+ commandCancel = (1 << 24),
+ burstCountShift = 8,
+ burstCountMask = ((1 << 16) -1), // 16 bits wide
+ stsValid = (1 << 7),
+ commandReady = (1 << 6),
+ tpmGo = (1 << 5),
+ dataAvail = (1 << 4),
+ Expect = (1 << 3),
+ selfTestDone = (1 << 2),
+ responseRetry = (1 << 1),
+};
+
+ // SPI frame header for TPM transactions is 4 bytes in size, it is described
+ // in section "6.4.6 Spi Bit Protocol" of the TCG issued "TPM Profile (PTP)
+ // Specification Revision 00.43.
+struct SpiFrameHeader {
+ unsigned char body[4];
+};
+
+TrunksFtdiSpi::~TrunksFtdiSpi() {
+ if (mpsse_)
+ Close(mpsse_);
+
+ mpsse_ = NULL;
+}
+
+bool TrunksFtdiSpi::ReadTpmSts(uint32_t *status) {
+ return FtdiReadReg(TPM_STS_REG, sizeof(*status), status);
+}
+
+bool TrunksFtdiSpi::WriteTpmSts(uint32_t status) {
+ return FtdiWriteReg(TPM_STS_REG, sizeof(status), &status);
+}
+
+void TrunksFtdiSpi::StartTransaction(bool read_write,
+ size_t bytes, unsigned addr) {
+ unsigned char *response;
+ SpiFrameHeader header;
+
+ usleep(10000); // give it 10 ms. TODO(vbendeb): remove this once
+ // cr50 SPS TPM driver performance is fixed.
+
+ // The first byte of the frame header encodes the transaction type (read or
+ // write) and size (set to lenth - 1).
+ header.body[0] = (read_write ? 0x80 : 0) | 0x40 | (bytes - 1);
+
+ // The rest of the frame header is the internal address in the TPM
+ for (int i = 0; i < 3; i++)
+ header.body[i + 1] = (addr >> (8 * (2 - i))) & 0xff;
+
+ Start(mpsse_);
+
+ response = Transfer(mpsse_, header.body, sizeof(header.body));
+
+ // The TCG TPM over SPI specification itroduces the notion of SPI flow
+ // control (Section "6.4.5 Flow Control" of the TCG issued "TPM Profile
+ // (PTP) Specification Revision 00.43).
+
+ // The slave (TPM device) expects each transaction to start with a 4 byte
+ // header trasmitted by master. If the slave needs to stall the transaction,
+ // it sets the MOSI bit to 0 during the last clock of the 4 byte header. In
+ // this case the master is supposed to start polling the line, byte at time,
+ // until the last bit in the received byte (transferred during the last
+ // clock of the byte) is set to 1.
+ while (!(response[3] & 1)) {
+ unsigned char *poll_state;
+
+ poll_state = Read(mpsse_, 1);
+ response[3] = *poll_state;
+ free(poll_state);
+ }
+ free(response);
+}
+
+bool TrunksFtdiSpi::FtdiWriteReg(unsigned reg_number, size_t bytes,
+ const void *buffer) {
+ if (!mpsse_)
+ return false;
+
+ StartTransaction(false, bytes, reg_number + locality_ * 0x10000);
+ Write(mpsse_, buffer, bytes);
+ Stop(mpsse_);
+ return true;
+}
+
+bool TrunksFtdiSpi::FtdiReadReg(unsigned reg_number, size_t bytes,
+ void *buffer) {
+ unsigned char *value;
+
+ if (!mpsse_)
+ return false;
+
+ StartTransaction(true, bytes, reg_number + locality_ * 0x10000);
+ value = Read(mpsse_, bytes);
+ if (buffer)
+ memcpy(buffer, value, bytes);
+ free(value);
+ Stop(mpsse_);
+ return true;
+}
+
+size_t TrunksFtdiSpi::GetBurstCount(void) {
+ uint32_t status;
+
+ ReadTpmSts(&status);
+ return (size_t)((status >> burstCountShift) & burstCountMask);
+}
+
+bool TrunksFtdiSpi::Init() {
+ uint32_t did_vid, status;
+ uint8_t cmd;
+
+ if (mpsse_)
+ return true;
+
+ mpsse_ = MPSSE(SPI0, ONE_MHZ, MSB);
+ if (!mpsse_)
+ return false;
+
+ // Reset the TPM using GPIOL0, issue a 100 ms long pulse.
+ PinLow(mpsse_, GPIOL0);
+ usleep(100000);
+ PinHigh(mpsse_, GPIOL0);
+
+ FtdiReadReg(TPM_DID_VID_REG, sizeof(did_vid), &did_vid);
+
+ uint16_t vid = did_vid & 0xffff;
+ if ((vid != 0x15d1) && (vid != 0x1ae0)) {
+ LOG(ERROR) << "unknown did_vid: 0x" << std::hex << did_vid;
+ return false;
+ }
+
+ // Try claiming locality zero.
+ FtdiReadReg(TPM_ACCESS_REG, sizeof(cmd), &cmd);
+ // tpmEstablishment can be either set or not.
+ if ((cmd & ~tpmEstablishment) != tpmRegValidSts) {
+ LOG(ERROR) << "invalid reset status: 0x" << std::hex << (unsigned)cmd;
+ return false;
+ }
+ cmd = requestUse;
+ FtdiWriteReg(TPM_ACCESS_REG, sizeof(cmd), &cmd);
+ FtdiReadReg(TPM_ACCESS_REG, sizeof(cmd), &cmd);
+ if ((cmd & ~tpmEstablishment) != (tpmRegValidSts | activeLocality)) {
+ LOG(ERROR) << "failed to claim locality, status: 0x" << std::hex
+ << (unsigned)cmd;
+ return false;
+ }
+
+ ReadTpmSts(&status);
+ if (((status >> tpmFamilyShift) & tpmFamilyMask) != tpmFamilyTPM2) {
+ LOG(ERROR) << "unexpected TPM family value, status: 0x" << std::hex
+ << status;
+ return false;
+ }
+ FtdiReadReg(TPM_RID_REG, sizeof(cmd), &cmd);
+ printf("Connected to device vid:did:rid of %4.4x:%4.4x:%2.2x\n",
+ did_vid & 0xffff, did_vid >> 16, cmd);
+
+ return true;
+}
+
+void TrunksFtdiSpi::SendCommand(const std::string& command,
+ const ResponseCallback& callback) {
+ printf("%s invoked\n", __func__);
+}
+
+bool TrunksFtdiSpi::WaitForStatus(uint32_t statusMask,
+ uint32_t statusExpected, int timeout_ms) {
+ uint32_t status;
+ time_t target_time;
+
+ target_time = time(NULL) + timeout_ms / 1000;
+ do {
+ usleep(10000); // 10 ms polling period.
+ if (time(NULL) >= target_time) {
+ LOG(ERROR) << "failed to get expected status " << std::hex
+ << statusExpected;
+ return false;
+ }
+ ReadTpmSts(&status);
+ } while ((status & statusMask) != statusExpected);
+ return true;
+}
+
+std::string TrunksFtdiSpi::SendCommandAndWait(const std::string& command) {
+ uint32_t status;
+ uint32_t expected_status_bits;
+ size_t transaction_size, handled_so_far(0);
+
+ std::string rv("");
+
+ if (!mpsse_) {
+ LOG(ERROR) << "attempt to use an uninitialized FTDI TPM!";
+ return rv;
+ }
+
+ WriteTpmSts(commandReady);
+
+ // No need to wait for the sts.Expect bit to be set, at least with the
+ // 15d1:001b device, let's just write the command into FIFO, not exceeding
+ // the minimum of the two values - burst_count and 64 (which is the protocol
+ // limitation)
+ do {
+ transaction_size = std::min(std::min(command.size() - handled_so_far,
+ GetBurstCount()),
+ (size_t)64);
+
+ if (transaction_size) {
+ LOG(INFO) << "will transfer " << transaction_size << " bytes";
+ FtdiWriteReg(TPM_DATA_FIFO_REG, transaction_size,
+ command.c_str() + handled_so_far);
+ handled_so_far += transaction_size;
+ }
+ } while (handled_so_far != command.size());
+
+ // And tell the device it can start processing it.
+ WriteTpmSts(tpmGo);
+
+ expected_status_bits = stsValid | dataAvail;
+ if (!WaitForStatus(expected_status_bits, expected_status_bits))
+ return rv;
+
+ // The response is ready, let's read it.
+ // First we read the FIFO payload header, to see how much data to expect.
+ // The header size is fixed to six bytes, the total payload size is stored
+ // in network order in the last four bytes of the header.
+ char data_header[6];
+
+ // Let's read the header first.
+ FtdiReadReg(TPM_DATA_FIFO_REG, sizeof(data_header), data_header);
+
+ // Figure out the total payload size.
+ uint32_t payload_size;
+ memcpy(&payload_size, data_header + 2, sizeof(payload_size));
+ payload_size = be32toh(payload_size);
+ // A FIFO message with the minimum required header and contents can not be
+ // less than 10 bytes long. It also should never be more than 4096 bytes
+ // long.
+ if ((payload_size < 10) || (payload_size > MAX_RESPONSE_SIZE)) {
+ // Something must be wrong...
+ LOG(ERROR) << "Bad total payload size value: " << payload_size;
+ return rv;
+ }
+
+ LOG(INFO) << "Total payload size " << payload_size;
+
+
+ // Let's read all but the last byte in the FIFO to make sure the status
+ // register is showing correct flow control bits: 'more data' until the last
+ // byte and then 'no more data' once the last byte is read.
+ handled_so_far = 0;
+ payload_size = payload_size - sizeof(data_header) - 1;
+ // Allow room for the last byte too.
+ uint8_t *payload = new uint8_t[payload_size + 1];
+ do {
+ transaction_size = std::min(std::min(payload_size - handled_so_far,
+ GetBurstCount()),
+ (size_t)64);
+
+ if (transaction_size) {
+ FtdiReadReg(TPM_DATA_FIFO_REG, transaction_size,
+ payload + handled_so_far);
+ handled_so_far += transaction_size;
+ }
+ } while (handled_so_far != payload_size);
+
+ // Verify that there is still data to come.
+ ReadTpmSts(&status);
+ if ((status & expected_status_bits) != expected_status_bits) {
+ LOG(ERROR) << "unexpected status 0x" << std::hex << status;
+ delete[] payload;
+ return rv;
+ }
+
+ // Now, read the last byte of the payload.
+ FtdiReadReg(TPM_DATA_FIFO_REG, sizeof(uint8_t), payload + payload_size);
+
+ // Verify that 'data available' is not asseretd any more.
+ ReadTpmSts(&status);
+ if ((status & expected_status_bits) != stsValid) {
+ LOG(ERROR) << "unexpected status 0x" << std::hex << status;
+ delete[] payload;
+ return rv;
+ }
+
+ rv = std::string(data_header, sizeof(data_header)) +
+ std::string(reinterpret_cast<char *>(payload), payload_size + 1);
+
+ /* Move the TPM back to idle state. */
+ WriteTpmSts(commandReady);
+
+ delete[] payload;
+ return rv;
+}
+
+} // namespace trunks
diff --git a/trunks/trunks_ftdi_spi.h b/trunks/trunks_ftdi_spi.h
new file mode 100644
index 0000000..de78f93
--- /dev/null
+++ b/trunks/trunks_ftdi_spi.h
@@ -0,0 +1,104 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_FTDI_SPI_H_
+#define TRUNKS_TRUNKS_FTDI_SPI_H_
+
+#include <string>
+
+#include <base/macros.h>
+
+#include "trunks/command_transceiver.h"
+#include "trunks/trunks_export.h"
+
+#if defined SPI_OVER_FTDI
+
+#include "trunks/ftdi/mpsse.h"
+
+namespace trunks {
+
+// TrunksFtdiSpi is a CommandTransceiver implementation that forwards all
+// commands to the SPI over FTDI interface directly to a TPM chip.
+class TRUNKS_EXPORT TrunksFtdiSpi: public CommandTransceiver {
+ public:
+ TrunksFtdiSpi() : mpsse_(NULL), locality_(0) {}
+ ~TrunksFtdiSpi() override;
+
+ // CommandTransceiver methods.
+ bool Init() override;
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) override;
+ std::string SendCommandAndWait(const std::string& command) override;
+
+ private:
+ struct mpsse_context* mpsse_;
+ unsigned locality_; // Set at initialization.
+
+ // Read a TPM register into the passed in buffer, where 'bytes' the width of
+ // the register. Return true on success, false on failure.
+ bool FtdiReadReg(unsigned reg_number, size_t bytes,
+ void *buffer);
+ // Write a TPM register from the passed in buffer, where 'bytes' the width of
+ // the register. Return true on success, false on failure.
+ bool FtdiWriteReg(unsigned reg_number, size_t bytes,
+ const void *buffer);
+ // Generate a proper SPI frame for read/write transaction, read_write set to
+ // true for read transactions, the size of the transaction is passed as
+ // 'bytes', addr is the internal TPM address space address (accounting for
+ // locality).
+ //
+ // Note that this function is expected to be called when the SPI bus is idle
+ // (CS deasserted), and will assert the CS before transmitting.
+ void StartTransaction(bool read_write, size_t bytes, unsigned addr);
+ // TPM Status Register is going to be accessed a lot, let's have dedicated
+ // accessors for it,
+ bool ReadTpmSts(uint32_t *status);
+ bool WriteTpmSts(uint32_t status);
+ // Poll status register until the required value is read or the timeout
+ // expires.
+ bool WaitForStatus(uint32_t statusMask,
+ uint32_t statusExpected, int timeout_ms = 10000);
+ // Retrieve current value of the burst count field.
+ size_t GetBurstCount(void);
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksFtdiSpi);
+};
+
+} // namespace trunks
+
+#else // SPI_OVER_FTDI ^^^^ defined vvvvv NOT defined
+
+namespace trunks {
+
+// A plug to support compilations on platforms where FTDI SPI interface is not
+// available.
+class TRUNKS_EXPORT TrunksFtdiSpi: public CommandTransceiver {
+ public:
+ TrunksFtdiSpi() {}
+ ~TrunksFtdiSpi() {}
+
+ bool Init() { return false; }
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) {}
+ std::string SendCommandAndWait(const std::string& command) {
+ return std::string(""); }
+};
+
+} // namespace trunks
+
+#endif // SPI_OVER_FTDI ^^^^ NOT defined
+
+#endif // TRUNKS_TRUNKS_FTDI_SPI_H_
diff --git a/trunks/trunks_proxy.cc b/trunks/trunks_proxy.cc
new file mode 100644
index 0000000..a37e006
--- /dev/null
+++ b/trunks/trunks_proxy.cc
@@ -0,0 +1,111 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/trunks_proxy.h"
+
+#include <base/bind.h>
+#include <brillo/bind_lambda.h>
+#include <brillo/dbus/dbus_method_invoker.h>
+
+#include "trunks/dbus_interface.h"
+#include "trunks/dbus_interface.pb.h"
+#include "trunks/error_codes.h"
+
+namespace {
+
+// Use a five minute timeout because some commands on some TPM hardware can take
+// a very long time. If a few lengthy operations are already in the queue, a
+// subsequent command needs to wait for all of them. Timeouts are always
+// possible but under normal conditions 5 minutes seems to be plenty.
+const int kDBusMaxTimeout = 5 * 60 * 1000;
+
+} // namespace
+
+namespace trunks {
+
+TrunksProxy::TrunksProxy() : weak_factory_(this) {}
+
+TrunksProxy::~TrunksProxy() {
+ if (bus_) {
+ bus_->ShutdownAndBlock();
+ }
+}
+
+bool TrunksProxy::Init() {
+ dbus::Bus::Options options;
+ options.bus_type = dbus::Bus::SYSTEM;
+ bus_ = new dbus::Bus(options);
+ object_proxy_ = bus_->GetObjectProxy(
+ trunks::kTrunksServiceName,
+ dbus::ObjectPath(trunks::kTrunksServicePath));
+ origin_thread_id_ = base::PlatformThread::CurrentId();
+ return (object_proxy_ != nullptr);
+}
+
+void TrunksProxy::SendCommand(const std::string& command,
+ const ResponseCallback& callback) {
+ if ((origin_thread_id_ != base::PlatformThread::CurrentId()) &&
+ (!Init())) {
+ LOG(ERROR) << "Error intializing trunks dbus proxy object.";
+ callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
+ }
+ SendCommandRequest tpm_command_proto;
+ tpm_command_proto.set_command(command);
+ auto on_error = [callback](brillo::Error* error) {
+ SendCommandResponse response;
+ response.set_response(CreateErrorResponse(SAPI_RC_NO_RESPONSE_RECEIVED));
+ callback.Run(response.response());
+ };
+ brillo::dbus_utils::CallMethodWithTimeout(
+ kDBusMaxTimeout,
+ object_proxy_,
+ trunks::kTrunksInterface,
+ trunks::kSendCommand,
+ callback,
+ base::Bind(on_error),
+ tpm_command_proto);
+}
+
+std::string TrunksProxy::SendCommandAndWait(const std::string& command) {
+ if ((origin_thread_id_ != base::PlatformThread::CurrentId()) &&
+ (!Init())) {
+ LOG(ERROR) << "Error intializing trunks dbus proxy object.";
+ return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
+ }
+ SendCommandRequest tpm_command_proto;
+ tpm_command_proto.set_command(command);
+ brillo::ErrorPtr error;
+ std::unique_ptr<dbus::Response> dbus_response =
+ brillo::dbus_utils::CallMethodAndBlockWithTimeout(
+ kDBusMaxTimeout,
+ object_proxy_,
+ trunks::kTrunksInterface,
+ trunks::kSendCommand,
+ &error,
+ tpm_command_proto);
+ SendCommandResponse tpm_response_proto;
+ if (dbus_response.get() && brillo::dbus_utils::ExtractMethodCallResults(
+ dbus_response.get(), &error, &tpm_response_proto)) {
+ return tpm_response_proto.response();
+ } else {
+ LOG(ERROR) << "TrunksProxy could not parse response: "
+ << error->GetMessage();
+ return CreateErrorResponse(SAPI_RC_MALFORMED_RESPONSE);
+ }
+}
+
+
+} // namespace trunks
diff --git a/trunks/trunks_proxy.h b/trunks/trunks_proxy.h
new file mode 100644
index 0000000..1951e0e
--- /dev/null
+++ b/trunks/trunks_proxy.h
@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_PROXY_H_
+#define TRUNKS_TRUNKS_PROXY_H_
+
+#include "trunks/command_transceiver.h"
+
+#include <string>
+
+#include <base/memory/weak_ptr.h>
+#include <base/threading/platform_thread.h>
+#include <dbus/bus.h>
+#include <dbus/object_proxy.h>
+
+#include "trunks/trunks_export.h"
+
+namespace trunks {
+
+// TrunksProxy is a CommandTransceiver implementation that forwards all commands
+// to the trunksd D-Bus daemon. See TrunksService for details on how the
+// commands are handled once they reach trunksd.
+class TRUNKS_EXPORT TrunksProxy: public CommandTransceiver {
+ public:
+ TrunksProxy();
+ ~TrunksProxy() override;
+
+ // Initializes the D-Bus client. Returns true on success.
+ bool Init() override;
+
+ // CommandTransceiver methods.
+ void SendCommand(const std::string& command,
+ const ResponseCallback& callback) override;
+ std::string SendCommandAndWait(const std::string& command) override;
+
+ private:
+ base::WeakPtr<TrunksProxy> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ base::PlatformThreadId origin_thread_id_;
+ scoped_refptr<dbus::Bus> bus_;
+ dbus::ObjectProxy* object_proxy_;
+
+ // Declared last so weak pointers are invalidated first on destruction.
+ base::WeakPtrFactory<TrunksProxy> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksProxy);
+};
+
+} // namespace trunks
+
+#endif // TRUNKS_TRUNKS_PROXY_H_
diff --git a/trunks/trunks_service.cc b/trunks/trunks_service.cc
new file mode 100644
index 0000000..f1aa34e
--- /dev/null
+++ b/trunks/trunks_service.cc
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include "trunks/trunks_service.h"
+
+#include <base/bind.h>
+#include <brillo/bind_lambda.h>
+
+#include "trunks/dbus_interface.h"
+#include "trunks/dbus_interface.pb.h"
+#include "trunks/error_codes.h"
+
+namespace trunks {
+
+using brillo::dbus_utils::DBusMethodResponse;
+
+TrunksService::TrunksService(const scoped_refptr<dbus::Bus>& bus,
+ CommandTransceiver* transceiver)
+ : trunks_dbus_object_(nullptr, bus, dbus::ObjectPath(kTrunksServicePath)),
+ transceiver_(transceiver),
+ weak_factory_(this) {}
+
+void TrunksService::Register(const CompletionAction& callback) {
+ brillo::dbus_utils::DBusInterface* dbus_interface =
+ trunks_dbus_object_.AddOrGetInterface(kTrunksInterface);
+ dbus_interface->AddMethodHandler(kSendCommand,
+ base::Unretained(this),
+ &TrunksService::HandleSendCommand);
+ trunks_dbus_object_.RegisterAsync(callback);
+}
+
+void TrunksService::HandleSendCommand(
+ std::unique_ptr<DBusMethodResponse<
+ const SendCommandResponse&>> response_sender,
+ const SendCommandRequest& request) {
+ // Convert |response_sender| to a shared_ptr so |transceiver_| can safely
+ // copy the callback.
+ using SharedResponsePointer = std::shared_ptr<
+ DBusMethodResponse<const SendCommandResponse&>>;
+ // A callback that constructs the response protobuf and sends it.
+ auto callback = [](const SharedResponsePointer& response,
+ const std::string& response_from_tpm) {
+ SendCommandResponse tpm_response_proto;
+ tpm_response_proto.set_response(response_from_tpm);
+ response->Return(tpm_response_proto);
+ };
+ if (!request.has_command() || request.command().empty()) {
+ LOG(ERROR) << "TrunksService: Invalid request.";
+ callback(SharedResponsePointer(std::move(response_sender)),
+ CreateErrorResponse(SAPI_RC_BAD_PARAMETER));
+ return;
+ }
+ transceiver_->SendCommand(
+ request.command(),
+ base::Bind(callback, SharedResponsePointer(std::move(response_sender))));
+}
+
+} // namespace trunks
diff --git a/trunks/trunks_service.h b/trunks/trunks_service.h
new file mode 100644
index 0000000..94ea16f
--- /dev/null
+++ b/trunks/trunks_service.h
@@ -0,0 +1,69 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#ifndef TRUNKS_TRUNKS_SERVICE_H_
+#define TRUNKS_TRUNKS_SERVICE_H_
+
+#include <string>
+
+#include <base/memory/weak_ptr.h>
+#include <brillo/dbus/dbus_method_response.h>
+#include <brillo/dbus/dbus_object.h>
+
+#include "trunks/dbus_interface.pb.h"
+#include "trunks/tpm_handle.h"
+
+namespace trunks {
+
+using CompletionAction =
+ brillo::dbus_utils::AsyncEventSequencer::CompletionAction;
+
+// TrunksService registers for and handles all incoming D-Bus messages for the
+// trunksd system daemon.
+class TrunksService {
+ public:
+ // The |transceiver| will be the target of all incoming TPM commands.
+ TrunksService(const scoped_refptr<dbus::Bus>& bus,
+ CommandTransceiver* transceiver);
+ virtual ~TrunksService() = default;
+
+ // Connects to D-Bus system bus and exports Trunks methods.
+ void Register(const CompletionAction& callback);
+
+ private:
+ // Handles calls to the 'SendCommand' method.
+ void HandleSendCommand(
+ std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+ const SendCommandResponse&>> response_sender,
+ const SendCommandRequest& request);
+
+ base::WeakPtr<TrunksService> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ brillo::dbus_utils::DBusObject trunks_dbus_object_;
+ CommandTransceiver* transceiver_;
+
+ // Declared last so weak pointers are invalidated first on destruction.
+ base::WeakPtrFactory<TrunksService> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksService);
+};
+
+} // namespace trunks
+
+
+#endif // TRUNKS_TRUNKS_SERVICE_H_
diff --git a/trunks/trunks_testrunner.cc b/trunks/trunks_testrunner.cc
new file mode 100644
index 0000000..9cbc9f9
--- /dev/null
+++ b/trunks/trunks_testrunner.cc
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include <base/at_exit.h>
+#include <base/command_line.h>
+#include <base/logging.h>
+#include <brillo/syslog_logging.h>
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+ base::CommandLine::Init(argc, argv);
+ brillo::InitLog(brillo::kLogToStderr);
+ // Enable verbose logging while running unit tests.
+ logging::SetMinLogLevel(logging::LOG_VERBOSE);
+ base::AtExitManager exit_manager;
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/trunks/trunksd-seccomp-amd64.policy b/trunks/trunksd-seccomp-amd64.policy
new file mode 100644
index 0000000..225e2ed
--- /dev/null
+++ b/trunks/trunksd-seccomp-amd64.policy
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+# Tested on lumpy
+gettid: 1
+getuid: 1
+geteuid: 1
+getgid: 1
+getegid: 1
+getresuid: 1
+getresgid: 1
+
+clock_getres: 1
+clock_gettime: 1
+gettimeofday: 1
+time: 1
+
+# Allow socket(domain==PF_LOCAL) or socket(domain==PF_NETLINK)
+socket: arg0 == 0x1 || arg0 == 0x10
+socketpair: 1
+connect: 1
+getsockname: 1
+pipe: 1
+sendmsg: 1
+sendto: 1
+recvmsg: 1
+
+epoll_create: 1
+epoll_wait: 1
+epoll_ctl: 1
+poll: 1
+
+read: 1
+write: 1
+close: 1
+
+fstat: 1
+stat: 1
+lseek: 1
+fcntl: 1
+
+futex: 1
+
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+
+brk: 1
+mmap: 1
+munmap: 1
+
+# Allow thread creation.
+mprotect: 1
+clone: 1
+set_robust_list: 1
+# This is attempted but apparently not necessary; return EPERM.
+prctl: return 1
+
+rt_sigprocmask: 1
+signalfd4: 1
diff --git a/trunks/trunksd-seccomp-arm.policy b/trunks/trunksd-seccomp-arm.policy
new file mode 100644
index 0000000..80af7a6
--- /dev/null
+++ b/trunks/trunksd-seccomp-arm.policy
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+# Tested on daisy
+gettid: 1
+getuid32: 1
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getresuid32: 1
+getresgid32: 1
+
+clock_getres: 1
+clock_gettime: 1
+gettimeofday: 1
+
+socket: arg0 == 0x1 || arg0 == 0x10
+socketpair: 1
+connect: 1
+getsockname: 1
+pipe: 1
+send: 1
+sendmsg: 1
+recvmsg: 1
+
+epoll_create: 1
+epoll_wait: 1
+epoll_ctl: 1
+poll: 1
+
+read: 1
+write: 1
+close: 1
+
+fstat64: 1
+stat64: 1
+_llseek: 1
+fcntl64: 1
+
+futex: 1
+
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+
+brk: 1
+mmap2: 1
+munmap: 1
diff --git a/trunks/trunksd-seccomp-x86.policy b/trunks/trunksd-seccomp-x86.policy
new file mode 100644
index 0000000..3c5495d
--- /dev/null
+++ b/trunks/trunksd-seccomp-x86.policy
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+# Tested on alex board
+gettid: 1
+getuid32: 1
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getresuid32: 1
+getresgid32: 1
+
+clock_getres: 1
+clock_gettime: 1
+gettimeofday: 1
+time: 1
+
+read: 1
+write: 1
+close: 1
+
+brk: 1
+mmap2: 1
+munmap: 1
+
+fstat64: 1
+stat64: 1
+_llseek: 1
+fcntl64: 1
+
+futex: 1
+
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+
+epoll_create: 1
+epoll_wait: 1
+epoll_ctl: 1
+poll: 1
diff --git a/trunks/trunksd.cc b/trunks/trunksd.cc
new file mode 100644
index 0000000..ecb047a
--- /dev/null
+++ b/trunks/trunksd.cc
@@ -0,0 +1,134 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.
+//
+
+#include <sysexits.h>
+
+#include <base/at_exit.h>
+#include <base/bind.h>
+#include <base/command_line.h>
+#include <base/threading/thread.h>
+#include <brillo/daemons/dbus_daemon.h>
+#include <brillo/minijail/minijail.h>
+#include <brillo/syslog_logging.h>
+#include <brillo/userdb_utils.h>
+
+#include "trunks/background_command_transceiver.h"
+#include "trunks/dbus_interface.h"
+#include "trunks/resource_manager.h"
+#include "trunks/tpm_handle.h"
+#include "trunks/tpm_simulator_handle.h"
+#include "trunks/trunks_factory_impl.h"
+#include "trunks/trunks_ftdi_spi.h"
+#include "trunks/trunks_service.h"
+
+using brillo::dbus_utils::AsyncEventSequencer;
+
+namespace {
+
+const uid_t kRootUID = 0;
+const char kTrunksUser[] = "trunks";
+const char kTrunksGroup[] = "trunks";
+const char kTrunksSeccompPath[] = "/usr/share/policy/trunksd-seccomp.policy";
+const char kBackgroundThreadName[] = "trunksd_background_thread";
+
+void InitMinijailSandbox() {
+ uid_t trunks_uid;
+ gid_t trunks_gid;
+ CHECK(brillo::userdb::GetUserInfo(kTrunksUser, &trunks_uid, &trunks_gid))
+ << "Error getting trunks uid and gid.";
+ CHECK_EQ(getuid(), kRootUID) << "Trunks Daemon not initialized as root.";
+ brillo::Minijail* minijail = brillo::Minijail::GetInstance();
+ struct minijail* jail = minijail->New();
+ minijail->DropRoot(jail, kTrunksUser, kTrunksGroup);
+ minijail->UseSeccompFilter(jail, kTrunksSeccompPath);
+ minijail->Enter(jail);
+ minijail->Destroy(jail);
+ CHECK_EQ(getuid(), trunks_uid)
+ << "TrunksDaemon was not able to drop to trunks user.";
+ CHECK_EQ(getgid(), trunks_gid)
+ << "TrunksDaemon was not able to drop to trunks group.";
+}
+
+} // namespace
+
+class TrunksDaemon : public brillo::DBusServiceDaemon {
+ public:
+ explicit TrunksDaemon(trunks::CommandTransceiver* transceiver) :
+ brillo::DBusServiceDaemon(trunks::kTrunksServiceName) {
+ transceiver_.reset(transceiver);
+ background_thread_.reset(new base::Thread(kBackgroundThreadName));
+ CHECK(background_thread_->Start());
+ // Chain together command transceivers:
+ // [IPC] --> TrunksService --> BackgroundCommandTransceiver -->
+ // ResourceManager --> TpmHandle --> [TPM]
+ factory_.reset(new trunks::TrunksFactoryImpl(transceiver_.get()));
+ resource_manager_.reset(new trunks::ResourceManager(
+ *factory_,
+ transceiver_.get()));
+ background_thread_->message_loop_proxy()->PostNonNestableTask(
+ FROM_HERE,
+ base::Bind(&trunks::ResourceManager::Initialize,
+ base::Unretained(resource_manager_.get())));
+ background_transceiver_.reset(
+ new trunks::BackgroundCommandTransceiver(
+ resource_manager_.get(),
+ background_thread_->message_loop_proxy()));
+ }
+
+ protected:
+ void RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) override {
+ trunks_service_.reset(new trunks::TrunksService(
+ bus_,
+ background_transceiver_.get()));
+ trunks_service_->Register(
+ sequencer->GetHandler("Register() failed.", true));
+ }
+
+
+ private:
+ std::unique_ptr<trunks::TrunksService> trunks_service_;
+ std::unique_ptr<trunks::CommandTransceiver> transceiver_;
+ // Thread for executing TPM comands.
+ std::unique_ptr<base::Thread> background_thread_;
+ std::unique_ptr<trunks::TrunksFactory> factory_;
+ std::unique_ptr<trunks::ResourceManager> resource_manager_;
+ std::unique_ptr<trunks::CommandTransceiver> background_transceiver_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrunksDaemon);
+};
+
+int main(int argc, char **argv) {
+ base::CommandLine::Init(argc, argv);
+ base::CommandLine *cl = base::CommandLine::ForCurrentProcess();
+ int flags = brillo::kLogToSyslog;
+ if (cl->HasSwitch("log_to_stderr")) {
+ flags |= brillo::kLogToStderr;
+ }
+ brillo::InitLog(flags);
+ trunks::CommandTransceiver *transceiver;
+ if (cl->HasSwitch("ftdi")) {
+ transceiver = new trunks::TrunksFtdiSpi();
+ } else if (cl->HasSwitch("simulator")) {
+ transceiver = new trunks::TpmSimulatorHandle();
+ } else {
+ transceiver = new trunks::TpmHandle();
+ }
+ CHECK(transceiver->Init()) << "Error initializing transceiver";
+ TrunksDaemon daemon(transceiver);
+ InitMinijailSandbox();
+ LOG(INFO) << "Trunks Service Started";
+ return daemon.Run();
+}
diff --git a/trunks/trunksd.conf b/trunks/trunksd.conf
new file mode 100644
index 0000000..68e4662
--- /dev/null
+++ b/trunks/trunksd.conf
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# 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.
+#
+
+description "Chromium OS trunks daemon for TPM2.0"
+author "chromium-os-dev@chromium.org"
+
+start on starting system-services
+stop on stopping system-services
+respawn
+
+exec trunksd