Add Nix flake for mciasctl and mciasgrpcctl
Vendor dependencies and expose control program binaries via nix build. Uses nixpkgs-unstable for Go 1.26 support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
202
vendor/github.com/google/go-tpm/LICENSE
generated
vendored
Normal file
202
vendor/github.com/google/go-tpm/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
35
vendor/github.com/google/go-tpm/legacy/tpm2/README.md
generated
vendored
Normal file
35
vendor/github.com/google/go-tpm/legacy/tpm2/README.md
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# TPM 2.0 client library
|
||||
|
||||
## Tests
|
||||
|
||||
This library contains unit tests in `github.com/google/go-tpm/tpm2`, which just
|
||||
tests that various encoding and error checking functions work correctly. It also
|
||||
contains more comprehensive integration tests in
|
||||
`github.com/google/go-tpm/tpm2/test`, which run actual commands on a TPM.
|
||||
|
||||
By default, these integration tests are run against the
|
||||
[`go-tpm-tools`](https://github.com/google/go-tpm-tools)
|
||||
simulator, which is baesed on the
|
||||
[Microsoft Reference TPM2 code](https://github.com/microsoft/ms-tpm-20-ref). To
|
||||
run both the unit and integration tests, run (in this directory)
|
||||
```bash
|
||||
go test . ./test
|
||||
```
|
||||
|
||||
These integration tests can also be run against a real TPM device. This is
|
||||
slightly more complex as the tests often need to be built as a normal user and
|
||||
then executed as root. For example,
|
||||
```bash
|
||||
# Build the test binary without running it
|
||||
go test -c github.com/google/go-tpm/tpm2/test
|
||||
# Execute the test binary as root
|
||||
sudo ./test.test --tpm-path=/dev/tpmrm0
|
||||
```
|
||||
On Linux, The `--tpm-path` causes the integration tests to be run against a
|
||||
real TPM located at that path (usually `/dev/tpmrm0` or `/dev/tpm0`). On Windows, the story is similar, execept that
|
||||
the `--use-tbs` flag is used instead.
|
||||
|
||||
Tip: if your TPM host is remote and you don't want to install Go on it, this
|
||||
same two-step process can be used. The test binary can be copied to a remote
|
||||
host and run without extra installation (as the test binary has very few
|
||||
*runtime* dependancies).
|
||||
576
vendor/github.com/google/go-tpm/legacy/tpm2/constants.go
generated
vendored
Normal file
576
vendor/github.com/google/go-tpm/legacy/tpm2/constants.go
generated
vendored
Normal file
@@ -0,0 +1,576 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
// Register the relevant hash implementations to prevent a runtime failure.
|
||||
_ "crypto/sha1"
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
)
|
||||
|
||||
var hashInfo = []struct {
|
||||
alg Algorithm
|
||||
hash crypto.Hash
|
||||
}{
|
||||
{AlgSHA1, crypto.SHA1},
|
||||
{AlgSHA256, crypto.SHA256},
|
||||
{AlgSHA384, crypto.SHA384},
|
||||
{AlgSHA512, crypto.SHA512},
|
||||
{AlgSHA3_256, crypto.SHA3_256},
|
||||
{AlgSHA3_384, crypto.SHA3_384},
|
||||
{AlgSHA3_512, crypto.SHA3_512},
|
||||
}
|
||||
|
||||
// MAX_DIGEST_BUFFER is the maximum size of []byte request or response fields.
|
||||
// Typically used for chunking of big blobs of data (such as for hashing or
|
||||
// encryption).
|
||||
const maxDigestBuffer = 1024
|
||||
|
||||
// Algorithm represents a TPM_ALG_ID value.
|
||||
type Algorithm uint16
|
||||
|
||||
// HashToAlgorithm looks up the TPM2 algorithm corresponding to the provided crypto.Hash
|
||||
func HashToAlgorithm(hash crypto.Hash) (Algorithm, error) {
|
||||
for _, info := range hashInfo {
|
||||
if info.hash == hash {
|
||||
return info.alg, nil
|
||||
}
|
||||
}
|
||||
return AlgUnknown, fmt.Errorf("go hash algorithm #%d has no TPM2 algorithm", hash)
|
||||
}
|
||||
|
||||
// IsNull returns true if a is AlgNull or zero (unset).
|
||||
func (a Algorithm) IsNull() bool {
|
||||
return a == AlgNull || a == AlgUnknown
|
||||
}
|
||||
|
||||
// UsesCount returns true if a signature algorithm uses count value.
|
||||
func (a Algorithm) UsesCount() bool {
|
||||
return a == AlgECDAA
|
||||
}
|
||||
|
||||
// UsesHash returns true if the algorithm requires the use of a hash.
|
||||
func (a Algorithm) UsesHash() bool {
|
||||
return a == AlgOAEP
|
||||
}
|
||||
|
||||
// Hash returns a crypto.Hash based on the given TPM_ALG_ID.
|
||||
// An error is returned if the given algorithm is not a hash algorithm or is not available.
|
||||
func (a Algorithm) Hash() (crypto.Hash, error) {
|
||||
for _, info := range hashInfo {
|
||||
if info.alg == a {
|
||||
if !info.hash.Available() {
|
||||
return crypto.Hash(0), fmt.Errorf("go hash algorithm #%d not available", info.hash)
|
||||
}
|
||||
return info.hash, nil
|
||||
}
|
||||
}
|
||||
return crypto.Hash(0), fmt.Errorf("hash algorithm not supported: 0x%x", a)
|
||||
}
|
||||
|
||||
func (a Algorithm) String() string {
|
||||
var s strings.Builder
|
||||
var err error
|
||||
switch a {
|
||||
case AlgUnknown:
|
||||
_, err = s.WriteString("AlgUnknown")
|
||||
case AlgRSA:
|
||||
_, err = s.WriteString("RSA")
|
||||
case AlgSHA1:
|
||||
_, err = s.WriteString("SHA1")
|
||||
case AlgHMAC:
|
||||
_, err = s.WriteString("HMAC")
|
||||
case AlgAES:
|
||||
_, err = s.WriteString("AES")
|
||||
case AlgKeyedHash:
|
||||
_, err = s.WriteString("KeyedHash")
|
||||
case AlgXOR:
|
||||
_, err = s.WriteString("XOR")
|
||||
case AlgSHA256:
|
||||
_, err = s.WriteString("SHA256")
|
||||
case AlgSHA384:
|
||||
_, err = s.WriteString("SHA384")
|
||||
case AlgSHA512:
|
||||
_, err = s.WriteString("SHA512")
|
||||
case AlgNull:
|
||||
_, err = s.WriteString("AlgNull")
|
||||
case AlgRSASSA:
|
||||
_, err = s.WriteString("RSASSA")
|
||||
case AlgRSAES:
|
||||
_, err = s.WriteString("RSAES")
|
||||
case AlgRSAPSS:
|
||||
_, err = s.WriteString("RSAPSS")
|
||||
case AlgOAEP:
|
||||
_, err = s.WriteString("OAEP")
|
||||
case AlgECDSA:
|
||||
_, err = s.WriteString("ECDSA")
|
||||
case AlgECDH:
|
||||
_, err = s.WriteString("ECDH")
|
||||
case AlgECDAA:
|
||||
_, err = s.WriteString("ECDAA")
|
||||
case AlgKDF2:
|
||||
_, err = s.WriteString("KDF2")
|
||||
case AlgECC:
|
||||
_, err = s.WriteString("ECC")
|
||||
case AlgSymCipher:
|
||||
_, err = s.WriteString("SymCipher")
|
||||
case AlgSHA3_256:
|
||||
_, err = s.WriteString("SHA3_256")
|
||||
case AlgSHA3_384:
|
||||
_, err = s.WriteString("SHA3_384")
|
||||
case AlgSHA3_512:
|
||||
_, err = s.WriteString("SHA3_512")
|
||||
case AlgCTR:
|
||||
_, err = s.WriteString("CTR")
|
||||
case AlgOFB:
|
||||
_, err = s.WriteString("OFB")
|
||||
case AlgCBC:
|
||||
_, err = s.WriteString("CBC")
|
||||
case AlgCFB:
|
||||
_, err = s.WriteString("CFB")
|
||||
case AlgECB:
|
||||
_, err = s.WriteString("ECB")
|
||||
default:
|
||||
return fmt.Sprintf("Alg?<%d>", int(a))
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Writing to string builder failed: %v", err)
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Supported Algorithms.
|
||||
const (
|
||||
AlgUnknown Algorithm = 0x0000
|
||||
AlgRSA Algorithm = 0x0001
|
||||
AlgSHA1 Algorithm = 0x0004
|
||||
AlgHMAC Algorithm = 0x0005
|
||||
AlgAES Algorithm = 0x0006
|
||||
AlgKeyedHash Algorithm = 0x0008
|
||||
AlgXOR Algorithm = 0x000A
|
||||
AlgSHA256 Algorithm = 0x000B
|
||||
AlgSHA384 Algorithm = 0x000C
|
||||
AlgSHA512 Algorithm = 0x000D
|
||||
AlgNull Algorithm = 0x0010
|
||||
AlgRSASSA Algorithm = 0x0014
|
||||
AlgRSAES Algorithm = 0x0015
|
||||
AlgRSAPSS Algorithm = 0x0016
|
||||
AlgOAEP Algorithm = 0x0017
|
||||
AlgECDSA Algorithm = 0x0018
|
||||
AlgECDH Algorithm = 0x0019
|
||||
AlgECDAA Algorithm = 0x001A
|
||||
AlgKDF2 Algorithm = 0x0021
|
||||
AlgECC Algorithm = 0x0023
|
||||
AlgSymCipher Algorithm = 0x0025
|
||||
AlgSHA3_256 Algorithm = 0x0027
|
||||
AlgSHA3_384 Algorithm = 0x0028
|
||||
AlgSHA3_512 Algorithm = 0x0029
|
||||
AlgCTR Algorithm = 0x0040
|
||||
AlgOFB Algorithm = 0x0041
|
||||
AlgCBC Algorithm = 0x0042
|
||||
AlgCFB Algorithm = 0x0043
|
||||
AlgECB Algorithm = 0x0044
|
||||
)
|
||||
|
||||
// HandleType defines a type of handle.
|
||||
type HandleType uint8
|
||||
|
||||
// Supported handle types
|
||||
const (
|
||||
HandleTypePCR HandleType = 0x00
|
||||
HandleTypeNVIndex HandleType = 0x01
|
||||
HandleTypeHMACSession HandleType = 0x02
|
||||
HandleTypeLoadedSession HandleType = 0x02
|
||||
HandleTypePolicySession HandleType = 0x03
|
||||
HandleTypeSavedSession HandleType = 0x03
|
||||
HandleTypePermanent HandleType = 0x40
|
||||
HandleTypeTransient HandleType = 0x80
|
||||
HandleTypePersistent HandleType = 0x81
|
||||
)
|
||||
|
||||
// SessionType defines the type of session created in StartAuthSession.
|
||||
type SessionType uint8
|
||||
|
||||
// Supported session types.
|
||||
const (
|
||||
SessionHMAC SessionType = 0x00
|
||||
SessionPolicy SessionType = 0x01
|
||||
SessionTrial SessionType = 0x03
|
||||
)
|
||||
|
||||
// SessionAttributes represents an attribute of a session.
|
||||
type SessionAttributes byte
|
||||
|
||||
// Session Attributes (Structures 8.4 TPMA_SESSION)
|
||||
const (
|
||||
AttrContinueSession SessionAttributes = 1 << iota
|
||||
AttrAuditExclusive
|
||||
AttrAuditReset
|
||||
_ // bit 3 reserved
|
||||
_ // bit 4 reserved
|
||||
AttrDecrypt
|
||||
AttrEcrypt
|
||||
AttrAudit
|
||||
)
|
||||
|
||||
// EmptyAuth represents the empty authorization value.
|
||||
var EmptyAuth []byte
|
||||
|
||||
// KeyProp is a bitmask used in Attributes field of key templates. Individual
|
||||
// flags should be OR-ed to form a full mask.
|
||||
type KeyProp uint32
|
||||
|
||||
// Key properties.
|
||||
const (
|
||||
FlagFixedTPM KeyProp = 0x00000002
|
||||
FlagStClear KeyProp = 0x00000004
|
||||
FlagFixedParent KeyProp = 0x00000010
|
||||
FlagSensitiveDataOrigin KeyProp = 0x00000020
|
||||
FlagUserWithAuth KeyProp = 0x00000040
|
||||
FlagAdminWithPolicy KeyProp = 0x00000080
|
||||
FlagNoDA KeyProp = 0x00000400
|
||||
FlagRestricted KeyProp = 0x00010000
|
||||
FlagDecrypt KeyProp = 0x00020000
|
||||
FlagSign KeyProp = 0x00040000
|
||||
|
||||
FlagSealDefault = FlagFixedTPM | FlagFixedParent
|
||||
FlagSignerDefault = FlagSign | FlagRestricted | FlagFixedTPM |
|
||||
FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth
|
||||
FlagStorageDefault = FlagDecrypt | FlagRestricted | FlagFixedTPM |
|
||||
FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth
|
||||
)
|
||||
|
||||
// TPMProp represents a Property Tag (TPM_PT) used with calls to GetCapability(CapabilityTPMProperties).
|
||||
type TPMProp uint32
|
||||
|
||||
// TPM Capability Properties, see TPM 2.0 Spec, Rev 1.38, Table 23.
|
||||
// Fixed TPM Properties (PT_FIXED)
|
||||
const (
|
||||
FamilyIndicator TPMProp = 0x100 + iota
|
||||
SpecLevel
|
||||
SpecRevision
|
||||
SpecDayOfYear
|
||||
SpecYear
|
||||
Manufacturer
|
||||
VendorString1
|
||||
VendorString2
|
||||
VendorString3
|
||||
VendorString4
|
||||
VendorTPMType
|
||||
FirmwareVersion1
|
||||
FirmwareVersion2
|
||||
InputMaxBufferSize
|
||||
TransientObjectsMin
|
||||
PersistentObjectsMin
|
||||
LoadedObjectsMin
|
||||
ActiveSessionsMax
|
||||
PCRCount
|
||||
PCRSelectMin
|
||||
ContextGapMax
|
||||
_ // (PT_FIXED + 21) is skipped
|
||||
NVCountersMax
|
||||
NVIndexMax
|
||||
MemoryMethod
|
||||
ClockUpdate
|
||||
ContextHash
|
||||
ContextSym
|
||||
ContextSymSize
|
||||
OrderlyCount
|
||||
CommandMaxSize
|
||||
ResponseMaxSize
|
||||
DigestMaxSize
|
||||
ObjectContextMaxSize
|
||||
SessionContextMaxSize
|
||||
PSFamilyIndicator
|
||||
PSSpecLevel
|
||||
PSSpecRevision
|
||||
PSSpecDayOfYear
|
||||
PSSpecYear
|
||||
SplitSigningMax
|
||||
TotalCommands
|
||||
LibraryCommands
|
||||
VendorCommands
|
||||
NVMaxBufferSize
|
||||
TPMModes
|
||||
CapabilityMaxBufferSize
|
||||
)
|
||||
|
||||
// Variable TPM Properties (PT_VAR)
|
||||
const (
|
||||
TPMAPermanent TPMProp = 0x200 + iota
|
||||
TPMAStartupClear
|
||||
HRNVIndex
|
||||
HRLoaded
|
||||
HRLoadedAvail
|
||||
HRActive
|
||||
HRActiveAvail
|
||||
HRTransientAvail
|
||||
CurrentPersistent
|
||||
AvailPersistent
|
||||
NVCounters
|
||||
NVCountersAvail
|
||||
AlgorithmSet
|
||||
LoadedCurves
|
||||
LockoutCounter
|
||||
MaxAuthFail
|
||||
LockoutInterval
|
||||
LockoutRecovery
|
||||
NVWriteRecovery
|
||||
AuditCounter0
|
||||
AuditCounter1
|
||||
)
|
||||
|
||||
// Allowed ranges of different kinds of Handles (TPM_HANDLE)
|
||||
// These constants have type TPMProp for backwards compatibility.
|
||||
const (
|
||||
PCRFirst TPMProp = 0x00000000
|
||||
HMACSessionFirst TPMProp = 0x02000000
|
||||
LoadedSessionFirst TPMProp = 0x02000000
|
||||
PolicySessionFirst TPMProp = 0x03000000
|
||||
ActiveSessionFirst TPMProp = 0x03000000
|
||||
TransientFirst TPMProp = 0x80000000
|
||||
PersistentFirst TPMProp = 0x81000000
|
||||
PersistentLast TPMProp = 0x81FFFFFF
|
||||
PlatformPersistent TPMProp = 0x81800000
|
||||
NVIndexFirst TPMProp = 0x01000000
|
||||
NVIndexLast TPMProp = 0x01FFFFFF
|
||||
PermanentFirst TPMProp = 0x40000000
|
||||
PermanentLast TPMProp = 0x4000010F
|
||||
)
|
||||
|
||||
// Reserved Handles.
|
||||
const (
|
||||
HandleOwner tpmutil.Handle = 0x40000001 + iota
|
||||
HandleRevoke
|
||||
HandleTransport
|
||||
HandleOperator
|
||||
HandleAdmin
|
||||
HandleEK
|
||||
HandleNull
|
||||
HandleUnassigned
|
||||
HandlePasswordSession
|
||||
HandleLockout
|
||||
HandleEndorsement
|
||||
HandlePlatform
|
||||
)
|
||||
|
||||
// Capability identifies some TPM property or state type.
|
||||
type Capability uint32
|
||||
|
||||
// TPM Capabilities.
|
||||
const (
|
||||
CapabilityAlgs Capability = iota
|
||||
CapabilityHandles
|
||||
CapabilityCommands
|
||||
CapabilityPPCommands
|
||||
CapabilityAuditCommands
|
||||
CapabilityPCRs
|
||||
CapabilityTPMProperties
|
||||
CapabilityPCRProperties
|
||||
CapabilityECCCurves
|
||||
CapabilityAuthPolicies
|
||||
)
|
||||
|
||||
// TPM Structure Tags. Tags are used to disambiguate structures, similar to Alg
|
||||
// values: tag value defines what kind of data lives in a nested field.
|
||||
const (
|
||||
TagNull tpmutil.Tag = 0x8000
|
||||
TagNoSessions tpmutil.Tag = 0x8001
|
||||
TagSessions tpmutil.Tag = 0x8002
|
||||
TagAttestCertify tpmutil.Tag = 0x8017
|
||||
TagAttestQuote tpmutil.Tag = 0x8018
|
||||
TagAttestCreation tpmutil.Tag = 0x801a
|
||||
TagAuthSecret tpmutil.Tag = 0x8023
|
||||
TagHashCheck tpmutil.Tag = 0x8024
|
||||
TagAuthSigned tpmutil.Tag = 0x8025
|
||||
)
|
||||
|
||||
// StartupType instructs the TPM on how to handle its state during Shutdown or
|
||||
// Startup.
|
||||
type StartupType uint16
|
||||
|
||||
// Startup types
|
||||
const (
|
||||
StartupClear StartupType = iota
|
||||
StartupState
|
||||
)
|
||||
|
||||
// EllipticCurve identifies specific EC curves.
|
||||
type EllipticCurve uint16
|
||||
|
||||
// ECC curves supported by TPM 2.0 spec.
|
||||
const (
|
||||
CurveNISTP192 = EllipticCurve(iota + 1)
|
||||
CurveNISTP224
|
||||
CurveNISTP256
|
||||
CurveNISTP384
|
||||
CurveNISTP521
|
||||
|
||||
CurveBNP256 = EllipticCurve(iota + 10)
|
||||
CurveBNP638
|
||||
|
||||
CurveSM2P256 = EllipticCurve(0x0020)
|
||||
)
|
||||
|
||||
var toGoCurve = map[EllipticCurve]elliptic.Curve{
|
||||
CurveNISTP224: elliptic.P224(),
|
||||
CurveNISTP256: elliptic.P256(),
|
||||
CurveNISTP384: elliptic.P384(),
|
||||
CurveNISTP521: elliptic.P521(),
|
||||
}
|
||||
|
||||
// Supported TPM operations.
|
||||
const (
|
||||
CmdNVUndefineSpaceSpecial tpmutil.Command = 0x0000011F
|
||||
CmdEvictControl tpmutil.Command = 0x00000120
|
||||
CmdUndefineSpace tpmutil.Command = 0x00000122
|
||||
CmdClear tpmutil.Command = 0x00000126
|
||||
CmdHierarchyChangeAuth tpmutil.Command = 0x00000129
|
||||
CmdDefineSpace tpmutil.Command = 0x0000012A
|
||||
CmdPCRAllocate tpmutil.Command = 0x0000012B
|
||||
CmdCreatePrimary tpmutil.Command = 0x00000131
|
||||
CmdIncrementNVCounter tpmutil.Command = 0x00000134
|
||||
CmdWriteNV tpmutil.Command = 0x00000137
|
||||
CmdWriteLockNV tpmutil.Command = 0x00000138
|
||||
CmdDictionaryAttackLockReset tpmutil.Command = 0x00000139
|
||||
CmdDictionaryAttackParameters tpmutil.Command = 0x0000013A
|
||||
CmdPCREvent tpmutil.Command = 0x0000013C
|
||||
CmdPCRReset tpmutil.Command = 0x0000013D
|
||||
CmdSequenceComplete tpmutil.Command = 0x0000013E
|
||||
CmdStartup tpmutil.Command = 0x00000144
|
||||
CmdShutdown tpmutil.Command = 0x00000145
|
||||
CmdActivateCredential tpmutil.Command = 0x00000147
|
||||
CmdCertify tpmutil.Command = 0x00000148
|
||||
CmdCertifyCreation tpmutil.Command = 0x0000014A
|
||||
CmdReadNV tpmutil.Command = 0x0000014E
|
||||
CmdReadLockNV tpmutil.Command = 0x0000014F
|
||||
CmdPolicySecret tpmutil.Command = 0x00000151
|
||||
CmdCreate tpmutil.Command = 0x00000153
|
||||
CmdECDHZGen tpmutil.Command = 0x00000154
|
||||
CmdImport tpmutil.Command = 0x00000156
|
||||
CmdLoad tpmutil.Command = 0x00000157
|
||||
CmdQuote tpmutil.Command = 0x00000158
|
||||
CmdRSADecrypt tpmutil.Command = 0x00000159
|
||||
CmdSequenceUpdate tpmutil.Command = 0x0000015C
|
||||
CmdSign tpmutil.Command = 0x0000015D
|
||||
CmdUnseal tpmutil.Command = 0x0000015E
|
||||
CmdPolicySigned tpmutil.Command = 0x00000160
|
||||
CmdContextLoad tpmutil.Command = 0x00000161
|
||||
CmdContextSave tpmutil.Command = 0x00000162
|
||||
CmdECDHKeyGen tpmutil.Command = 0x00000163
|
||||
CmdEncryptDecrypt tpmutil.Command = 0x00000164
|
||||
CmdFlushContext tpmutil.Command = 0x00000165
|
||||
CmdLoadExternal tpmutil.Command = 0x00000167
|
||||
CmdMakeCredential tpmutil.Command = 0x00000168
|
||||
CmdReadPublicNV tpmutil.Command = 0x00000169
|
||||
CmdPolicyCommandCode tpmutil.Command = 0x0000016C
|
||||
CmdPolicyOr tpmutil.Command = 0x00000171
|
||||
CmdReadPublic tpmutil.Command = 0x00000173
|
||||
CmdRSAEncrypt tpmutil.Command = 0x00000174
|
||||
CmdStartAuthSession tpmutil.Command = 0x00000176
|
||||
CmdGetCapability tpmutil.Command = 0x0000017A
|
||||
CmdGetRandom tpmutil.Command = 0x0000017B
|
||||
CmdHash tpmutil.Command = 0x0000017D
|
||||
CmdPCRRead tpmutil.Command = 0x0000017E
|
||||
CmdPolicyPCR tpmutil.Command = 0x0000017F
|
||||
CmdReadClock tpmutil.Command = 0x00000181
|
||||
CmdPCRExtend tpmutil.Command = 0x00000182
|
||||
CmdEventSequenceComplete tpmutil.Command = 0x00000185
|
||||
CmdHashSequenceStart tpmutil.Command = 0x00000186
|
||||
CmdPolicyGetDigest tpmutil.Command = 0x00000189
|
||||
CmdPolicyPassword tpmutil.Command = 0x0000018C
|
||||
CmdEncryptDecrypt2 tpmutil.Command = 0x00000193
|
||||
)
|
||||
|
||||
// Regular TPM 2.0 devices use 24-bit mask (3 bytes) for PCR selection.
|
||||
const sizeOfPCRSelect = 3
|
||||
|
||||
const defaultRSAExponent = 1<<16 + 1
|
||||
|
||||
// NVAttr is a bitmask used in Attributes field of NV indexes. Individual
|
||||
// flags should be OR-ed to form a full mask.
|
||||
type NVAttr uint32
|
||||
|
||||
// NV Attributes
|
||||
const (
|
||||
AttrPPWrite NVAttr = 0x00000001
|
||||
AttrOwnerWrite NVAttr = 0x00000002
|
||||
AttrAuthWrite NVAttr = 0x00000004
|
||||
AttrPolicyWrite NVAttr = 0x00000008
|
||||
AttrPolicyDelete NVAttr = 0x00000400
|
||||
AttrWriteLocked NVAttr = 0x00000800
|
||||
AttrWriteAll NVAttr = 0x00001000
|
||||
AttrWriteDefine NVAttr = 0x00002000
|
||||
AttrWriteSTClear NVAttr = 0x00004000
|
||||
AttrGlobalLock NVAttr = 0x00008000
|
||||
AttrPPRead NVAttr = 0x00010000
|
||||
AttrOwnerRead NVAttr = 0x00020000
|
||||
AttrAuthRead NVAttr = 0x00040000
|
||||
AttrPolicyRead NVAttr = 0x00080000
|
||||
AttrNoDA NVAttr = 0x02000000
|
||||
AttrOrderly NVAttr = 0x04000000
|
||||
AttrClearSTClear NVAttr = 0x08000000
|
||||
AttrReadLocked NVAttr = 0x10000000
|
||||
AttrWritten NVAttr = 0x20000000
|
||||
AttrPlatformCreate NVAttr = 0x40000000
|
||||
AttrReadSTClear NVAttr = 0x80000000
|
||||
)
|
||||
|
||||
var permMap = map[NVAttr]string{
|
||||
AttrPPWrite: "PPWrite",
|
||||
AttrOwnerWrite: "OwnerWrite",
|
||||
AttrAuthWrite: "AuthWrite",
|
||||
AttrPolicyWrite: "PolicyWrite",
|
||||
AttrPolicyDelete: "PolicyDelete",
|
||||
AttrWriteLocked: "WriteLocked",
|
||||
AttrWriteAll: "WriteAll",
|
||||
AttrWriteDefine: "WriteDefine",
|
||||
AttrWriteSTClear: "WriteSTClear",
|
||||
AttrGlobalLock: "GlobalLock",
|
||||
AttrPPRead: "PPRead",
|
||||
AttrOwnerRead: "OwnerRead",
|
||||
AttrAuthRead: "AuthRead",
|
||||
AttrPolicyRead: "PolicyRead",
|
||||
AttrNoDA: "No Do",
|
||||
AttrOrderly: "Oderly",
|
||||
AttrClearSTClear: "ClearSTClear",
|
||||
AttrReadLocked: "ReadLocked",
|
||||
AttrWritten: "Writte",
|
||||
AttrPlatformCreate: "PlatformCreate",
|
||||
AttrReadSTClear: "ReadSTClear",
|
||||
}
|
||||
|
||||
// String returns a textual representation of the set of NVAttr
|
||||
func (p NVAttr) String() string {
|
||||
var retString strings.Builder
|
||||
for iterator, item := range permMap {
|
||||
if (p & iterator) != 0 {
|
||||
retString.WriteString(item + " + ")
|
||||
}
|
||||
}
|
||||
if retString.String() == "" {
|
||||
return "Permission/s not found"
|
||||
}
|
||||
return strings.TrimSuffix(retString.String(), " + ")
|
||||
|
||||
}
|
||||
362
vendor/github.com/google/go-tpm/legacy/tpm2/error.go
generated
vendored
Normal file
362
vendor/github.com/google/go-tpm/legacy/tpm2/error.go
generated
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
)
|
||||
|
||||
type (
|
||||
// RCFmt0 holds Format 0 error codes
|
||||
RCFmt0 uint8
|
||||
|
||||
// RCFmt1 holds Format 1 error codes
|
||||
RCFmt1 uint8
|
||||
|
||||
// RCWarn holds error codes used in warnings
|
||||
RCWarn uint8
|
||||
|
||||
// RCIndex is used to reference arguments, handles and sessions in errors
|
||||
RCIndex uint8
|
||||
)
|
||||
|
||||
// Format 0 error codes.
|
||||
const (
|
||||
RCInitialize RCFmt0 = 0x00
|
||||
RCFailure RCFmt0 = 0x01
|
||||
RCSequence RCFmt0 = 0x03
|
||||
RCPrivate RCFmt0 = 0x0B
|
||||
RCHMAC RCFmt0 = 0x19
|
||||
RCDisabled RCFmt0 = 0x20
|
||||
RCExclusive RCFmt0 = 0x21
|
||||
RCAuthType RCFmt0 = 0x24
|
||||
RCAuthMissing RCFmt0 = 0x25
|
||||
RCPolicy RCFmt0 = 0x26
|
||||
RCPCR RCFmt0 = 0x27
|
||||
RCPCRChanged RCFmt0 = 0x28
|
||||
RCUpgrade RCFmt0 = 0x2D
|
||||
RCTooManyContexts RCFmt0 = 0x2E
|
||||
RCAuthUnavailable RCFmt0 = 0x2F
|
||||
RCReboot RCFmt0 = 0x30
|
||||
RCUnbalanced RCFmt0 = 0x31
|
||||
RCCommandSize RCFmt0 = 0x42
|
||||
RCCommandCode RCFmt0 = 0x43
|
||||
RCAuthSize RCFmt0 = 0x44
|
||||
RCAuthContext RCFmt0 = 0x45
|
||||
RCNVRange RCFmt0 = 0x46
|
||||
RCNVSize RCFmt0 = 0x47
|
||||
RCNVLocked RCFmt0 = 0x48
|
||||
RCNVAuthorization RCFmt0 = 0x49
|
||||
RCNVUninitialized RCFmt0 = 0x4A
|
||||
RCNVSpace RCFmt0 = 0x4B
|
||||
RCNVDefined RCFmt0 = 0x4C
|
||||
RCBadContext RCFmt0 = 0x50
|
||||
RCCPHash RCFmt0 = 0x51
|
||||
RCParent RCFmt0 = 0x52
|
||||
RCNeedsTest RCFmt0 = 0x53
|
||||
RCNoResult RCFmt0 = 0x54
|
||||
RCSensitive RCFmt0 = 0x55
|
||||
)
|
||||
|
||||
var fmt0Msg = map[RCFmt0]string{
|
||||
RCInitialize: "TPM not initialized by TPM2_Startup or already initialized",
|
||||
RCFailure: "commands not being accepted because of a TPM failure",
|
||||
RCSequence: "improper use of a sequence handle",
|
||||
RCPrivate: "not currently used",
|
||||
RCHMAC: "not currently used",
|
||||
RCDisabled: "the command is disabled",
|
||||
RCExclusive: "command failed because audit sequence required exclusivity",
|
||||
RCAuthType: "authorization handle is not correct for command",
|
||||
RCAuthMissing: "5 command requires an authorization session for handle and it is not present",
|
||||
RCPolicy: "policy failure in math operation or an invalid authPolicy value",
|
||||
RCPCR: "PCR check fail",
|
||||
RCPCRChanged: "PCR have changed since checked",
|
||||
RCUpgrade: "TPM is in field upgrade mode unless called via TPM2_FieldUpgradeData(), then it is not in field upgrade mode",
|
||||
RCTooManyContexts: "context ID counter is at maximum",
|
||||
RCAuthUnavailable: "authValue or authPolicy is not available for selected entity",
|
||||
RCReboot: "a _TPM_Init and Startup(CLEAR) is required before the TPM can resume operation",
|
||||
RCUnbalanced: "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",
|
||||
RCCommandSize: "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",
|
||||
RCCommandCode: "command code not supported",
|
||||
RCAuthSize: "the value of authorizationSize is out of range or the number of octets in the Authorization Area is greater than required",
|
||||
RCAuthContext: "use of an authorization session with a context command or another command that cannot have an authorization session",
|
||||
RCNVRange: "NV offset+size is out of range",
|
||||
RCNVSize: "Requested allocation size is larger than allowed",
|
||||
RCNVLocked: "NV access locked",
|
||||
RCNVAuthorization: "NV access authorization fails in command actions",
|
||||
RCNVUninitialized: "an NV Index is used before being initialized or the state saved by TPM2_Shutdown(STATE) could not be restored",
|
||||
RCNVSpace: "insufficient space for NV allocation",
|
||||
RCNVDefined: "NV Index or persistent object already defined",
|
||||
RCBadContext: "context in TPM2_ContextLoad() is not valid",
|
||||
RCCPHash: "cpHash value already set or not correct for use",
|
||||
RCParent: "handle for parent is not a valid parent",
|
||||
RCNeedsTest: "some function needs testing",
|
||||
RCNoResult: "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",
|
||||
RCSensitive: "the sensitive area did not unmarshal correctly after decryption",
|
||||
}
|
||||
|
||||
// Format 1 error codes.
|
||||
const (
|
||||
RCAsymmetric = 0x01
|
||||
RCAttributes = 0x02
|
||||
RCHash = 0x03
|
||||
RCValue = 0x04
|
||||
RCHierarchy = 0x05
|
||||
RCKeySize = 0x07
|
||||
RCMGF = 0x08
|
||||
RCMode = 0x09
|
||||
RCType = 0x0A
|
||||
RCHandle = 0x0B
|
||||
RCKDF = 0x0C
|
||||
RCRange = 0x0D
|
||||
RCAuthFail = 0x0E
|
||||
RCNonce = 0x0F
|
||||
RCPP = 0x10
|
||||
RCScheme = 0x12
|
||||
RCSize = 0x15
|
||||
RCSymmetric = 0x16
|
||||
RCTag = 0x17
|
||||
RCSelector = 0x18
|
||||
RCInsufficient = 0x1A
|
||||
RCSignature = 0x1B
|
||||
RCKey = 0x1C
|
||||
RCPolicyFail = 0x1D
|
||||
RCIntegrity = 0x1F
|
||||
RCTicket = 0x20
|
||||
RCReservedBits = 0x21
|
||||
RCBadAuth = 0x22
|
||||
RCExpired = 0x23
|
||||
RCPolicyCC = 0x24
|
||||
RCBinding = 0x25
|
||||
RCCurve = 0x26
|
||||
RCECCPoint = 0x27
|
||||
)
|
||||
|
||||
var fmt1Msg = map[RCFmt1]string{
|
||||
RCAsymmetric: "asymmetric algorithm not supported or not correct",
|
||||
RCAttributes: "inconsistent attributes",
|
||||
RCHash: "hash algorithm not supported or not appropriate",
|
||||
RCValue: "value is out of range or is not correct for the context",
|
||||
RCHierarchy: "hierarchy is not enabled or is not correct for the use",
|
||||
RCKeySize: "key size is not supported",
|
||||
RCMGF: "mask generation function not supported",
|
||||
RCMode: "mode of operation not supported",
|
||||
RCType: "the type of the value is not appropriate for the use",
|
||||
RCHandle: "the handle is not correct for the use",
|
||||
RCKDF: "unsupported key derivation function or function not appropriate for use",
|
||||
RCRange: "value was out of allowed range",
|
||||
RCAuthFail: "the authorization HMAC check failed and DA counter incremented",
|
||||
RCNonce: "invalid nonce size or nonce value mismatch",
|
||||
RCPP: "authorization requires assertion of PP",
|
||||
RCScheme: "unsupported or incompatible scheme",
|
||||
RCSize: "structure is the wrong size",
|
||||
RCSymmetric: "unsupported symmetric algorithm or key size, or not appropriate for instance",
|
||||
RCTag: "incorrect structure tag",
|
||||
RCSelector: "union selector is incorrect",
|
||||
RCInsufficient: "the TPM was unable to unmarshal a value because there were not enough octets in the input buffer",
|
||||
RCSignature: "the signature is not valid",
|
||||
RCKey: "key fields are not compatible with the selected use",
|
||||
RCPolicyFail: "a policy check failed",
|
||||
RCIntegrity: "integrity check failed",
|
||||
RCTicket: "invalid ticket",
|
||||
RCReservedBits: "reserved bits not set to zero as required",
|
||||
RCBadAuth: "authorization failure without DA implications",
|
||||
RCExpired: "the policy has expired",
|
||||
RCPolicyCC: "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",
|
||||
RCBinding: "public and sensitive portions of an object are not cryptographically bound",
|
||||
RCCurve: "curve not supported",
|
||||
RCECCPoint: "point is not on the required curve",
|
||||
}
|
||||
|
||||
// Warning codes.
|
||||
const (
|
||||
RCContextGap RCWarn = 0x01
|
||||
RCObjectMemory RCWarn = 0x02
|
||||
RCSessionMemory RCWarn = 0x03
|
||||
RCMemory RCWarn = 0x04
|
||||
RCSessionHandles RCWarn = 0x05
|
||||
RCObjectHandles RCWarn = 0x06
|
||||
RCLocality RCWarn = 0x07
|
||||
RCYielded RCWarn = 0x08
|
||||
RCCanceled RCWarn = 0x09
|
||||
RCTesting RCWarn = 0x0A
|
||||
RCReferenceH0 RCWarn = 0x10
|
||||
RCReferenceH1 RCWarn = 0x11
|
||||
RCReferenceH2 RCWarn = 0x12
|
||||
RCReferenceH3 RCWarn = 0x13
|
||||
RCReferenceH4 RCWarn = 0x14
|
||||
RCReferenceH5 RCWarn = 0x15
|
||||
RCReferenceH6 RCWarn = 0x16
|
||||
RCReferenceS0 RCWarn = 0x18
|
||||
RCReferenceS1 RCWarn = 0x19
|
||||
RCReferenceS2 RCWarn = 0x1A
|
||||
RCReferenceS3 RCWarn = 0x1B
|
||||
RCReferenceS4 RCWarn = 0x1C
|
||||
RCReferenceS5 RCWarn = 0x1D
|
||||
RCReferenceS6 RCWarn = 0x1E
|
||||
RCNVRate RCWarn = 0x20
|
||||
RCLockout RCWarn = 0x21
|
||||
RCRetry RCWarn = 0x22
|
||||
RCNVUnavailable RCWarn = 0x23
|
||||
)
|
||||
|
||||
var warnMsg = map[RCWarn]string{
|
||||
RCContextGap: "gap for context ID is too large",
|
||||
RCObjectMemory: "out of memory for object contexts",
|
||||
RCSessionMemory: "out of memory for session contexts",
|
||||
RCMemory: "out of shared object/session memory or need space for internal operations",
|
||||
RCSessionHandles: "out of session handles",
|
||||
RCObjectHandles: "out of object handles",
|
||||
RCLocality: "bad locality",
|
||||
RCYielded: "the TPM has suspended operation on the command; forward progress was made and the command may be retried",
|
||||
RCCanceled: "the command was canceled",
|
||||
RCTesting: "TPM is performing self-tests",
|
||||
RCReferenceH0: "the 1st handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceH1: "the 2nd handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceH2: "the 3rd handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceH3: "the 4th handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceH4: "the 5th handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceH5: "the 6th handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceH6: "the 7th handle in the handle area references a transient object or session that is not loaded",
|
||||
RCReferenceS0: "the 1st authorization session handle references a session that is not loaded",
|
||||
RCReferenceS1: "the 2nd authorization session handle references a session that is not loaded",
|
||||
RCReferenceS2: "the 3rd authorization session handle references a session that is not loaded",
|
||||
RCReferenceS3: "the 4th authorization session handle references a session that is not loaded",
|
||||
RCReferenceS4: "the 5th authorization session handle references a session that is not loaded",
|
||||
RCReferenceS5: "the 6th authorization session handle references a session that is not loaded",
|
||||
RCReferenceS6: "the 7th authorization session handle references a session that is not loaded",
|
||||
RCNVRate: "the TPM is rate-limiting accesses to prevent wearout of NV",
|
||||
RCLockout: "authorizations for objects subject to DA protection are not allowed at this time because the TPM is in DA lockout mode",
|
||||
RCRetry: "the TPM was not able to start the command",
|
||||
RCNVUnavailable: "the command may require writing of NV and NV is not current accessible",
|
||||
}
|
||||
|
||||
// Indexes for arguments, handles and sessions.
|
||||
const (
|
||||
RC1 RCIndex = iota + 1
|
||||
RC2
|
||||
RC3
|
||||
RC4
|
||||
RC5
|
||||
RC6
|
||||
RC7
|
||||
RC8
|
||||
RC9
|
||||
RCA
|
||||
RCB
|
||||
RCC
|
||||
RCD
|
||||
RCE
|
||||
RCF
|
||||
)
|
||||
|
||||
const unknownCode = "unknown error code"
|
||||
|
||||
// Error is returned for all Format 0 errors from the TPM. It is used for general
|
||||
// errors not specific to a parameter, handle or session.
|
||||
type Error struct {
|
||||
Code RCFmt0
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
msg := fmt0Msg[e.Code]
|
||||
if msg == "" {
|
||||
msg = unknownCode
|
||||
}
|
||||
return fmt.Sprintf("error code 0x%x : %s", e.Code, msg)
|
||||
}
|
||||
|
||||
// VendorError represents a vendor-specific error response. These types of responses
|
||||
// are not decoded and Code contains the complete response code.
|
||||
type VendorError struct {
|
||||
Code uint32
|
||||
}
|
||||
|
||||
func (e VendorError) Error() string {
|
||||
return fmt.Sprintf("vendor error code 0x%x", e.Code)
|
||||
}
|
||||
|
||||
// Warning is typically used to report transient errors.
|
||||
type Warning struct {
|
||||
Code RCWarn
|
||||
}
|
||||
|
||||
func (w Warning) Error() string {
|
||||
msg := warnMsg[w.Code]
|
||||
if msg == "" {
|
||||
msg = unknownCode
|
||||
}
|
||||
return fmt.Sprintf("warning code 0x%x : %s", w.Code, msg)
|
||||
}
|
||||
|
||||
// ParameterError describes an error related to a parameter, and the parameter number.
|
||||
type ParameterError struct {
|
||||
Code RCFmt1
|
||||
Parameter RCIndex
|
||||
}
|
||||
|
||||
func (e ParameterError) Error() string {
|
||||
msg := fmt1Msg[e.Code]
|
||||
if msg == "" {
|
||||
msg = unknownCode
|
||||
}
|
||||
return fmt.Sprintf("parameter %d, error code 0x%x : %s", e.Parameter, e.Code, msg)
|
||||
}
|
||||
|
||||
// HandleError describes an error related to a handle, and the handle number.
|
||||
type HandleError struct {
|
||||
Code RCFmt1
|
||||
Handle RCIndex
|
||||
}
|
||||
|
||||
func (e HandleError) Error() string {
|
||||
msg := fmt1Msg[e.Code]
|
||||
if msg == "" {
|
||||
msg = unknownCode
|
||||
}
|
||||
return fmt.Sprintf("handle %d, error code 0x%x : %s", e.Handle, e.Code, msg)
|
||||
}
|
||||
|
||||
// SessionError describes an error related to a session, and the session number.
|
||||
type SessionError struct {
|
||||
Code RCFmt1
|
||||
Session RCIndex
|
||||
}
|
||||
|
||||
func (e SessionError) Error() string {
|
||||
msg := fmt1Msg[e.Code]
|
||||
if msg == "" {
|
||||
msg = unknownCode
|
||||
}
|
||||
return fmt.Sprintf("session %d, error code 0x%x : %s", e.Session, e.Code, msg)
|
||||
}
|
||||
|
||||
// Decode a TPM2 response code and return the appropriate error. Logic
|
||||
// according to the "Response Code Evaluation" chart in Part 1 of the TPM 2.0
|
||||
// spec.
|
||||
func decodeResponse(code tpmutil.ResponseCode) error {
|
||||
if code == tpmutil.RCSuccess {
|
||||
return nil
|
||||
}
|
||||
if code&0x180 == 0 { // Bits 7:8 == 0 is a TPM1 error
|
||||
return fmt.Errorf("response status 0x%x", code)
|
||||
}
|
||||
if code&0x80 == 0 { // Bit 7 unset
|
||||
if code&0x400 > 0 { // Bit 10 set, vendor specific code
|
||||
return VendorError{uint32(code)}
|
||||
}
|
||||
if code&0x800 > 0 { // Bit 11 set, warning with code in bit 0:6
|
||||
return Warning{RCWarn(code & 0x7f)}
|
||||
}
|
||||
// error with code in bit 0:6
|
||||
return Error{RCFmt0(code & 0x7f)}
|
||||
}
|
||||
if code&0x40 > 0 { // Bit 6 set, code in 0:5, parameter number in 8:11
|
||||
return ParameterError{RCFmt1(code & 0x3f), RCIndex((code & 0xf00) >> 8)}
|
||||
}
|
||||
if code&0x800 == 0 { // Bit 11 unset, code in 0:5, handle in 8:10
|
||||
return HandleError{RCFmt1(code & 0x3f), RCIndex((code & 0x700) >> 8)}
|
||||
}
|
||||
// Code in 0:5, Session in 8:10
|
||||
return SessionError{RCFmt1(code & 0x3f), RCIndex((code & 0x700) >> 8)}
|
||||
}
|
||||
116
vendor/github.com/google/go-tpm/legacy/tpm2/kdf.go
generated
vendored
Normal file
116
vendor/github.com/google/go-tpm/legacy/tpm2/kdf.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// KDFa implements TPM 2.0's default key derivation function, as defined in
|
||||
// section 11.4.9.2 of the TPM revision 2 specification part 1.
|
||||
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
|
||||
// The key & label parameters must not be zero length.
|
||||
// The label parameter is a non-null-terminated string.
|
||||
// The contextU & contextV parameters are optional.
|
||||
// Deprecated: Use KDFaHash.
|
||||
func KDFa(hashAlg Algorithm, key []byte, label string, contextU, contextV []byte, bits int) ([]byte, error) {
|
||||
h, err := hashAlg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return KDFaHash(h, key, label, contextU, contextV, bits), nil
|
||||
}
|
||||
|
||||
// KDFe implements TPM 2.0's ECDH key derivation function, as defined in
|
||||
// section 11.4.9.3 of the TPM revision 2 specification part 1.
|
||||
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
|
||||
// The z parameter is the x coordinate of one party's private ECC key multiplied
|
||||
// by the other party's public ECC point.
|
||||
// The use parameter is a non-null-terminated string.
|
||||
// The partyUInfo and partyVInfo are the x coordinates of the initiator's and
|
||||
// Deprecated: Use KDFeHash.
|
||||
func KDFe(hashAlg Algorithm, z []byte, use string, partyUInfo, partyVInfo []byte, bits int) ([]byte, error) {
|
||||
h, err := hashAlg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return KDFeHash(h, z, use, partyUInfo, partyVInfo, bits), nil
|
||||
}
|
||||
|
||||
// KDFaHash implements TPM 2.0's default key derivation function, as defined in
|
||||
// section 11.4.9.2 of the TPM revision 2 specification part 1.
|
||||
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
|
||||
// The key & label parameters must not be zero length.
|
||||
// The label parameter is a non-null-terminated string.
|
||||
// The contextU & contextV parameters are optional.
|
||||
func KDFaHash(h crypto.Hash, key []byte, label string, contextU, contextV []byte, bits int) []byte {
|
||||
mac := hmac.New(h.New, key)
|
||||
|
||||
out := kdf(mac, bits, func() {
|
||||
mac.Write([]byte(label))
|
||||
mac.Write([]byte{0}) // Terminating null character for C-string.
|
||||
mac.Write(contextU)
|
||||
mac.Write(contextV)
|
||||
binary.Write(mac, binary.BigEndian, uint32(bits))
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
// KDFeHash implements TPM 2.0's ECDH key derivation function, as defined in
|
||||
// section 11.4.9.3 of the TPM revision 2 specification part 1.
|
||||
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
|
||||
// The z parameter is the x coordinate of one party's private ECC key multiplied
|
||||
// by the other party's public ECC point.
|
||||
// The use parameter is a non-null-terminated string.
|
||||
// The partyUInfo and partyVInfo are the x coordinates of the initiator's and
|
||||
// the responder's ECC points, respectively.
|
||||
func KDFeHash(h crypto.Hash, z []byte, use string, partyUInfo, partyVInfo []byte, bits int) []byte {
|
||||
hash := h.New()
|
||||
|
||||
out := kdf(hash, bits, func() {
|
||||
hash.Write(z)
|
||||
hash.Write([]byte(use))
|
||||
hash.Write([]byte{0}) // Terminating null character for C-string.
|
||||
hash.Write(partyUInfo)
|
||||
hash.Write(partyVInfo)
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
func kdf(h hash.Hash, bits int, update func()) []byte {
|
||||
bytes := (bits + 7) / 8
|
||||
out := []byte{}
|
||||
|
||||
for counter := 1; len(out) < bytes; counter++ {
|
||||
h.Reset()
|
||||
binary.Write(h, binary.BigEndian, uint32(counter))
|
||||
update()
|
||||
|
||||
out = h.Sum(out)
|
||||
}
|
||||
// out's length is a multiple of hash size, so there will be excess
|
||||
// bytes if bytes isn't a multiple of hash size.
|
||||
out = out[:bytes]
|
||||
|
||||
// As mentioned in the KDFa and KDFe specs mentioned above,
|
||||
// the unused bits of the most significant octet are masked off.
|
||||
if maskBits := uint8(bits % 8); maskBits > 0 {
|
||||
out[0] &= (1 << maskBits) - 1
|
||||
}
|
||||
return out
|
||||
}
|
||||
57
vendor/github.com/google/go-tpm/legacy/tpm2/open_other.go
generated
vendored
Normal file
57
vendor/github.com/google/go-tpm/legacy/tpm2/open_other.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
//go:build !windows
|
||||
|
||||
// Copyright (c) 2019, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
)
|
||||
|
||||
// OpenTPM opens a channel to the TPM at the given path. If the file is a
|
||||
// device, then it treats it like a normal TPM device, and if the file is a
|
||||
// Unix domain socket, then it opens a connection to the socket.
|
||||
//
|
||||
// This function may also be invoked with no paths, as tpm2.OpenTPM(). In this
|
||||
// case, the default paths on Linux (/dev/tpmrm0 then /dev/tpm0), will be used.
|
||||
func OpenTPM(path ...string) (tpm io.ReadWriteCloser, err error) {
|
||||
switch len(path) {
|
||||
case 0:
|
||||
tpm, err = tpmutil.OpenTPM("/dev/tpmrm0")
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
tpm, err = tpmutil.OpenTPM("/dev/tpm0")
|
||||
}
|
||||
case 1:
|
||||
tpm, err = tpmutil.OpenTPM(path[0])
|
||||
default:
|
||||
return nil, errors.New("cannot specify multiple paths to tpm2.OpenTPM")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make sure this is a TPM 2.0
|
||||
_, err = GetManufacturer(tpm)
|
||||
if err != nil {
|
||||
tpm.Close()
|
||||
return nil, fmt.Errorf("open %s: device is not a TPM 2.0", path)
|
||||
}
|
||||
return tpm, nil
|
||||
}
|
||||
39
vendor/github.com/google/go-tpm/legacy/tpm2/open_windows.go
generated
vendored
Normal file
39
vendor/github.com/google/go-tpm/legacy/tpm2/open_windows.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
//go:build windows
|
||||
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
"github.com/google/go-tpm/tpmutil/tbs"
|
||||
)
|
||||
|
||||
// OpenTPM opens a channel to the TPM.
|
||||
func OpenTPM() (io.ReadWriteCloser, error) {
|
||||
info, err := tbs.GetDeviceInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if info.TPMVersion != tbs.TPMVersion20 {
|
||||
return nil, fmt.Errorf("openTPM: device is not a TPM 2.0")
|
||||
}
|
||||
|
||||
return tpmutil.OpenTPM()
|
||||
}
|
||||
1112
vendor/github.com/google/go-tpm/legacy/tpm2/structures.go
generated
vendored
Normal file
1112
vendor/github.com/google/go-tpm/legacy/tpm2/structures.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2354
vendor/github.com/google/go-tpm/legacy/tpm2/tpm2.go
generated
vendored
Normal file
2354
vendor/github.com/google/go-tpm/legacy/tpm2/tpm2.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
87
vendor/github.com/google/go-tpm/tpm2/audit.go
generated
vendored
Normal file
87
vendor/github.com/google/go-tpm/tpm2/audit.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// CommandAudit represents an audit session for attesting the execution of a
|
||||
// series of commands in the TPM. It is useful for both command and session
|
||||
// auditing.
|
||||
type CommandAudit struct {
|
||||
hash TPMIAlgHash
|
||||
digest []byte
|
||||
}
|
||||
|
||||
// NewAudit initializes a new CommandAudit with the specified hash algorithm.
|
||||
func NewAudit(hash TPMIAlgHash) (*CommandAudit, error) {
|
||||
h, err := hash.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &CommandAudit{
|
||||
hash: hash,
|
||||
digest: make([]byte, h.Size()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AuditCommand extends the audit digest with the given command and response.
|
||||
// Go Generics do not allow type parameters on methods, otherwise this would be
|
||||
// a method on CommandAudit.
|
||||
// See https://github.com/golang/go/issues/49085 for more information.
|
||||
func AuditCommand[C Command[R, *R], R any](a *CommandAudit, cmd C, rsp *R) error {
|
||||
cc := cmd.Command()
|
||||
cpHash, err := auditCPHash[R](cc, a.hash, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpHash, err := auditRPHash(cc, a.hash, rsp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ha, err := a.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h := ha.New()
|
||||
h.Write(a.digest)
|
||||
h.Write(cpHash)
|
||||
h.Write(rpHash)
|
||||
a.digest = h.Sum(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Digest returns the current digest of the audit.
|
||||
func (a *CommandAudit) Digest() []byte {
|
||||
return a.digest
|
||||
}
|
||||
|
||||
// auditCPHash calculates the command parameter hash for a given command with
|
||||
// the given hash algorithm. The command is assumed to not have any decrypt
|
||||
// sessions.
|
||||
func auditCPHash[R any](cc TPMCC, h TPMIAlgHash, c Command[R, *R]) ([]byte, error) {
|
||||
names, err := cmdNames(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parms, err := cmdParameters(c, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cpHash(h, cc, names, parms)
|
||||
}
|
||||
|
||||
// auditRPHash calculates the response parameter hash for a given response with
|
||||
// the given hash algorithm. The command is assumed to be successful and to not
|
||||
// have any encrypt sessions.
|
||||
func auditRPHash(cc TPMCC, h TPMIAlgHash, r any) ([]byte, error) {
|
||||
var parms bytes.Buffer
|
||||
parameters := taggedMembers(reflect.ValueOf(r).Elem(), "handle", true)
|
||||
for i, parameter := range parameters {
|
||||
if err := marshal(&parms, parameter); err != nil {
|
||||
return nil, fmt.Errorf("marshalling parameter %v: %w", i+1, err)
|
||||
}
|
||||
}
|
||||
return rpHash(h, TPMRCSuccess, cc, parms.Bytes())
|
||||
}
|
||||
82
vendor/github.com/google/go-tpm/tpm2/bitfield.go
generated
vendored
Normal file
82
vendor/github.com/google/go-tpm/tpm2/bitfield.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Bitfield represents a TPM bitfield (i.e., TPMA_*) type.
|
||||
type Bitfield interface {
|
||||
// Length returns the length of the bitfield.
|
||||
Length() int
|
||||
}
|
||||
|
||||
// BitGetter represents a TPM bitfield (i.e., TPMA_*) type that can be read.
|
||||
type BitGetter interface {
|
||||
Bitfield
|
||||
// GetReservedBit returns the value of the given reserved bit.
|
||||
// If the bit is not reserved, returns false.
|
||||
GetReservedBit(pos int) bool
|
||||
}
|
||||
|
||||
// BitSetter represents a TPM bitfield (i.e., TPMA_*) type that can be written.
|
||||
type BitSetter interface {
|
||||
Bitfield
|
||||
// GetReservedBit sets the value of the given reserved bit.
|
||||
SetReservedBit(pos int, val bool)
|
||||
}
|
||||
|
||||
func checkPos(pos int, len int) {
|
||||
if pos >= len || pos < 0 {
|
||||
panic(fmt.Errorf("bit %d out of range for %d-bit field", pos, len))
|
||||
}
|
||||
}
|
||||
|
||||
// bitfield8 represents an 8-bit bitfield which may have reserved bits.
|
||||
// 8-bit TPMA_* types embed this one, and the reserved bits are stored in it.
|
||||
type bitfield8 uint8
|
||||
|
||||
// Length implements the Bitfield interface.
|
||||
func (bitfield8) Length() int {
|
||||
return 8
|
||||
}
|
||||
|
||||
// GetReservedBit implements the BitGetter interface.
|
||||
func (r bitfield8) GetReservedBit(pos int) bool {
|
||||
checkPos(pos, 8)
|
||||
return r&(1<<pos) != 0
|
||||
}
|
||||
|
||||
// SetReservedBit implements the BitSetter interface.
|
||||
func (r *bitfield8) SetReservedBit(pos int, val bool) {
|
||||
checkPos(pos, 8)
|
||||
if val {
|
||||
*r |= 1 << pos
|
||||
} else {
|
||||
*r &= ^(1 << pos)
|
||||
}
|
||||
}
|
||||
|
||||
// bitfield32 represents a 32-bit bitfield which may have reserved bits.
|
||||
// 32-bit TPMA_* types embed this one, and the reserved bits are stored in it.
|
||||
type bitfield32 uint32
|
||||
|
||||
// Length implements the Bitfield interface.
|
||||
func (bitfield32) Length() int {
|
||||
return 32
|
||||
}
|
||||
|
||||
// GetReservedBit implements the BitGetter interface.
|
||||
func (r bitfield32) GetReservedBit(pos int) bool {
|
||||
checkPos(pos, 32)
|
||||
return r&(1<<pos) != 0
|
||||
}
|
||||
|
||||
// SetReservedBit implements the BitSetter interface.
|
||||
func (r *bitfield32) SetReservedBit(pos int, val bool) {
|
||||
checkPos(pos, 32)
|
||||
if val {
|
||||
*r |= 1 << pos
|
||||
} else {
|
||||
*r &= ^(1 << pos)
|
||||
}
|
||||
}
|
||||
62
vendor/github.com/google/go-tpm/tpm2/child_object_crypto.go
generated
vendored
Normal file
62
vendor/github.com/google/go-tpm/tpm2/child_object_crypto.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
labelStorage = "STORAGE"
|
||||
labelIntegrity = "INTEGRITY"
|
||||
|
||||
ErrUnsupportedCipher = errors.New("unsupported block cipher")
|
||||
ErrUnsupportedMode = errors.New("unsupported block cipher mode of operation")
|
||||
)
|
||||
|
||||
// deriveAndEncrypt derives a symmetric key and uses it to encrypt the plaintext.
|
||||
func deriveAndEncrypt(pub LabeledEncapsulationKey, seed []byte, context []byte, plaintext []byte) ([]byte, error) {
|
||||
// Only AES is supported.
|
||||
if pub.SymmetricParameters().Algorithm != TPMAlgAES {
|
||||
return nil, fmt.Errorf("%w %v", ErrUnsupportedCipher, pub.SymmetricParameters().Algorithm)
|
||||
}
|
||||
mode, err := pub.SymmetricParameters().Mode.AES()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if *mode != TPMAlgCFB {
|
||||
return nil, fmt.Errorf("%w %v", ErrUnsupportedMode, *mode)
|
||||
}
|
||||
bits, err := pub.SymmetricParameters().KeyBits.AES()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash, err := pub.NameAlg().Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := aes.NewCipher(KDFa(hash, seed, labelStorage, context, nil, int(*bits)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ciphertext := make([]byte, len(plaintext))
|
||||
cipher.NewCFBEncrypter(key, make([]byte, key.BlockSize())).XORKeyStream(ciphertext, plaintext)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// deriveAndHMAC derives an HMAC key and uses it to HMAC the data, which can be provided in multiple chunks.
|
||||
func deriveAndHMAC(pub LabeledEncapsulationKey, seed []byte, data ...[]byte) ([]byte, error) {
|
||||
hash, err := pub.NameAlg().Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := KDFa(hash, seed, labelIntegrity, nil, nil, hash.Size()*8)
|
||||
hmac := hmac.New(hash.New, key)
|
||||
for _, data := range data {
|
||||
hmac.Write(data)
|
||||
}
|
||||
return hmac.Sum(nil), nil
|
||||
}
|
||||
718
vendor/github.com/google/go-tpm/tpm2/constants.go
generated
vendored
Normal file
718
vendor/github.com/google/go-tpm/tpm2/constants.go
generated
vendored
Normal file
@@ -0,0 +1,718 @@
|
||||
package tpm2
|
||||
|
||||
//go:generate stringer -trimprefix=TPM -type=TPMAlgID,TPMECCCurve,TPMCC,TPMRC,TPMEO,TPMST,TPMCap,TPMPT,TPMPTPCR,TPMHT,TPMHandle,TPMNT -output=constants_string.go constants.go
|
||||
|
||||
import (
|
||||
|
||||
// Register the relevant hash implementations.
|
||||
_ "crypto/sha1"
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
)
|
||||
|
||||
// TPMAlgID represents a TPM_ALG_ID.
|
||||
// See definition in Part 2: Structures, section 6.3.
|
||||
type TPMAlgID uint16
|
||||
|
||||
// TPMAlgID values come from Part 2: Structures, section 6.3.
|
||||
const (
|
||||
TPMAlgRSA TPMAlgID = 0x0001
|
||||
TPMAlgTDES TPMAlgID = 0x0003
|
||||
TPMAlgSHA1 TPMAlgID = 0x0004
|
||||
TPMAlgHMAC TPMAlgID = 0x0005
|
||||
TPMAlgAES TPMAlgID = 0x0006
|
||||
TPMAlgMGF1 TPMAlgID = 0x0007
|
||||
TPMAlgKeyedHash TPMAlgID = 0x0008
|
||||
TPMAlgXOR TPMAlgID = 0x000A
|
||||
TPMAlgSHA256 TPMAlgID = 0x000B
|
||||
TPMAlgSHA384 TPMAlgID = 0x000C
|
||||
TPMAlgSHA512 TPMAlgID = 0x000D
|
||||
TPMAlgSHA256192 TPMAlgID = 0x000E
|
||||
TPMAlgNull TPMAlgID = 0x0010
|
||||
TPMAlgSM3256 TPMAlgID = 0x0012
|
||||
TPMAlgSM4 TPMAlgID = 0x0013
|
||||
TPMAlgRSASSA TPMAlgID = 0x0014
|
||||
TPMAlgRSAES TPMAlgID = 0x0015
|
||||
TPMAlgRSAPSS TPMAlgID = 0x0016
|
||||
TPMAlgOAEP TPMAlgID = 0x0017
|
||||
TPMAlgECDSA TPMAlgID = 0x0018
|
||||
TPMAlgECDH TPMAlgID = 0x0019
|
||||
TPMAlgECDAA TPMAlgID = 0x001A
|
||||
TPMAlgSM2 TPMAlgID = 0x001B
|
||||
TPMAlgECSchnorr TPMAlgID = 0x001C
|
||||
TPMAlgECMQV TPMAlgID = 0x001D
|
||||
TPMAlgKDF1SP80056A TPMAlgID = 0x0020
|
||||
TPMAlgKDF2 TPMAlgID = 0x0021
|
||||
TPMAlgKDF1SP800108 TPMAlgID = 0x0022
|
||||
TPMAlgECC TPMAlgID = 0x0023
|
||||
TPMAlgSymCipher TPMAlgID = 0x0025
|
||||
TPMAlgCamellia TPMAlgID = 0x0026
|
||||
TPMAlgSHA3256 TPMAlgID = 0x0027
|
||||
TPMAlgSHA3384 TPMAlgID = 0x0028
|
||||
TPMAlgSHA3512 TPMAlgID = 0x0029
|
||||
TPMAlgSHAKE128 TPMAlgID = 0x002A
|
||||
TPMAlgSHAKE256 TPMAlgID = 0x002B
|
||||
TPMAlgSHAKE256192 TPMAlgID = 0x002C
|
||||
TPMAlgSHAKE256256 TPMAlgID = 0x002D
|
||||
TPMAlgSHAKE256512 TPMAlgID = 0x002E
|
||||
TPMAlgCMAC TPMAlgID = 0x003F
|
||||
TPMAlgCTR TPMAlgID = 0x0040
|
||||
TPMAlgOFB TPMAlgID = 0x0041
|
||||
TPMAlgCBC TPMAlgID = 0x0042
|
||||
TPMAlgCFB TPMAlgID = 0x0043
|
||||
TPMAlgECB TPMAlgID = 0x0044
|
||||
TPMAlgCCM TPMAlgID = 0x0050
|
||||
TPMAlgGCM TPMAlgID = 0x0051
|
||||
TPMAlgKW TPMAlgID = 0x0052
|
||||
TPMAlgKWP TPMAlgID = 0x0053
|
||||
TPMAlgEAX TPMAlgID = 0x0054
|
||||
TPMAlgEDDSA TPMAlgID = 0x0060
|
||||
TPMAlgEDDSAPH TPMAlgID = 0x0061
|
||||
TPMAlgLMS TPMAlgID = 0x0070
|
||||
TPMAlgXMSS TPMAlgID = 0x0071
|
||||
TPMAlgKEYEDXOF TPMAlgID = 0x0080
|
||||
TPMAlgKMACXOF128 TPMAlgID = 0x0081
|
||||
TPMAlgKMACXOF256 TPMAlgID = 0x0082
|
||||
TPMAlgKMAC128 TPMAlgID = 0x0090
|
||||
TPMAlgKMAC256 TPMAlgID = 0x0091
|
||||
)
|
||||
|
||||
// TPMECCCurve represents a TPM_ECC_Curve.
|
||||
// See definition in Part 2: Structures, section 6.4.
|
||||
type TPMECCCurve uint16
|
||||
|
||||
// TPMECCCurve values come from Part 2: Structures, section 6.4.
|
||||
const (
|
||||
TPMECCNone TPMECCCurve = 0x0000
|
||||
TPMECCNistP192 TPMECCCurve = 0x0001
|
||||
TPMECCNistP224 TPMECCCurve = 0x0002
|
||||
TPMECCNistP256 TPMECCCurve = 0x0003
|
||||
TPMECCNistP384 TPMECCCurve = 0x0004
|
||||
TPMECCNistP521 TPMECCCurve = 0x0005
|
||||
TPMECCBNP256 TPMECCCurve = 0x0010
|
||||
TPMECCBNP638 TPMECCCurve = 0x0011
|
||||
TPMECCSM2P256 TPMECCCurve = 0x0020
|
||||
TPMECCBrainpoolP256R1 TPMECCCurve = 0x0030
|
||||
TPMECCBrainpoolP384R1 TPMECCCurve = 0x0031
|
||||
TPMECCBrainpoolP512R1 TPMECCCurve = 0x0032
|
||||
TPMECCCurve25519 TPMECCCurve = 0x0040
|
||||
TPMECCCurve448 TPMECCCurve = 0x0041
|
||||
)
|
||||
|
||||
// TPMCC represents a TPM_CC.
|
||||
// See definition in Part 2: Structures, section 6.5.2.
|
||||
type TPMCC uint32
|
||||
|
||||
// TPMCC values come from Part 2: Structures, section 6.5.2.
|
||||
const (
|
||||
TPMCCNVUndefineSpaceSpecial TPMCC = 0x0000011F
|
||||
TPMCCEvictControl TPMCC = 0x00000120
|
||||
TPMCCHierarchyControl TPMCC = 0x00000121
|
||||
TPMCCNVUndefineSpace TPMCC = 0x00000122
|
||||
TPMCCChangeEPS TPMCC = 0x00000124
|
||||
TPMCCChangePPS TPMCC = 0x00000125
|
||||
TPMCCClear TPMCC = 0x00000126
|
||||
TPMCCClearControl TPMCC = 0x00000127
|
||||
TPMCCClockSet TPMCC = 0x00000128
|
||||
TPMCCHierarchyChanegAuth TPMCC = 0x00000129
|
||||
TPMCCNVDefineSpace TPMCC = 0x0000012A
|
||||
TPMCCPCRAllocate TPMCC = 0x0000012B
|
||||
TPMCCPCRSetAuthPolicy TPMCC = 0x0000012C
|
||||
TPMCCPPCommands TPMCC = 0x0000012D
|
||||
TPMCCSetPrimaryPolicy TPMCC = 0x0000012E
|
||||
TPMCCFieldUpgradeStart TPMCC = 0x0000012F
|
||||
TPMCCClockRateAdjust TPMCC = 0x00000130
|
||||
TPMCCCreatePrimary TPMCC = 0x00000131
|
||||
TPMCCNVGlobalWriteLock TPMCC = 0x00000132
|
||||
TPMCCGetCommandAuditDigest TPMCC = 0x00000133
|
||||
TPMCCNVIncrement TPMCC = 0x00000134
|
||||
TPMCCNVSetBits TPMCC = 0x00000135
|
||||
TPMCCNVExtend TPMCC = 0x00000136
|
||||
TPMCCNVWrite TPMCC = 0x00000137
|
||||
TPMCCNVWriteLock TPMCC = 0x00000138
|
||||
TPMCCDictionaryAttackLockReset TPMCC = 0x00000139
|
||||
TPMCCDictionaryAttackParameters TPMCC = 0x0000013A
|
||||
TPMCCNVChangeAuth TPMCC = 0x0000013B
|
||||
TPMCCPCREvent TPMCC = 0x0000013C
|
||||
TPMCCPCRReset TPMCC = 0x0000013D
|
||||
TPMCCSequenceComplete TPMCC = 0x0000013E
|
||||
TPMCCSetAlgorithmSet TPMCC = 0x0000013F
|
||||
TPMCCSetCommandCodeAuditStatus TPMCC = 0x00000140
|
||||
TPMCCFieldUpgradeData TPMCC = 0x00000141
|
||||
TPMCCIncrementalSelfTest TPMCC = 0x00000142
|
||||
TPMCCSelfTest TPMCC = 0x00000143
|
||||
TPMCCStartup TPMCC = 0x00000144
|
||||
TPMCCShutdown TPMCC = 0x00000145
|
||||
TPMCCStirRandom TPMCC = 0x00000146
|
||||
TPMCCActivateCredential TPMCC = 0x00000147
|
||||
TPMCCCertify TPMCC = 0x00000148
|
||||
TPMCCPolicyNV TPMCC = 0x00000149
|
||||
TPMCCCertifyCreation TPMCC = 0x0000014A
|
||||
TPMCCDuplicate TPMCC = 0x0000014B
|
||||
TPMCCGetTime TPMCC = 0x0000014C
|
||||
TPMCCGetSessionAuditDigest TPMCC = 0x0000014D
|
||||
TPMCCNVRead TPMCC = 0x0000014E
|
||||
TPMCCNVReadLock TPMCC = 0x0000014F
|
||||
TPMCCObjectChangeAuth TPMCC = 0x00000150
|
||||
TPMCCPolicySecret TPMCC = 0x00000151
|
||||
TPMCCRewrap TPMCC = 0x00000152
|
||||
TPMCCCreate TPMCC = 0x00000153
|
||||
TPMCCECDHZGen TPMCC = 0x00000154
|
||||
TPMCCMAC TPMCC = 0x00000155
|
||||
TPMCCImport TPMCC = 0x00000156
|
||||
TPMCCLoad TPMCC = 0x00000157
|
||||
TPMCCQuote TPMCC = 0x00000158
|
||||
TPMCCRSADecrypt TPMCC = 0x00000159
|
||||
TPMCCMACStart TPMCC = 0x0000015B
|
||||
TPMCCSequenceUpdate TPMCC = 0x0000015C
|
||||
TPMCCSign TPMCC = 0x0000015D
|
||||
TPMCCUnseal TPMCC = 0x0000015E
|
||||
TPMCCPolicySigned TPMCC = 0x00000160
|
||||
TPMCCContextLoad TPMCC = 0x00000161
|
||||
TPMCCContextSave TPMCC = 0x00000162
|
||||
TPMCCECDHKeyGen TPMCC = 0x00000163
|
||||
TPMCCEncryptDecrypt TPMCC = 0x00000164
|
||||
TPMCCFlushContext TPMCC = 0x00000165
|
||||
TPMCCLoadExternal TPMCC = 0x00000167
|
||||
TPMCCMakeCredential TPMCC = 0x00000168
|
||||
TPMCCNVReadPublic TPMCC = 0x00000169
|
||||
TPMCCPolicyAuthorize TPMCC = 0x0000016A
|
||||
TPMCCPolicyAuthValue TPMCC = 0x0000016B
|
||||
TPMCCPolicyCommandCode TPMCC = 0x0000016C
|
||||
TPMCCPolicyCounterTimer TPMCC = 0x0000016D
|
||||
TPMCCPolicyCpHash TPMCC = 0x0000016E
|
||||
TPMCCPolicyLocality TPMCC = 0x0000016F
|
||||
TPMCCPolicyNameHash TPMCC = 0x00000170
|
||||
TPMCCPolicyOR TPMCC = 0x00000171
|
||||
TPMCCPolicyTicket TPMCC = 0x00000172
|
||||
TPMCCReadPublic TPMCC = 0x00000173
|
||||
TPMCCRSAEncrypt TPMCC = 0x00000174
|
||||
TPMCCStartAuthSession TPMCC = 0x00000176
|
||||
TPMCCVerifySignature TPMCC = 0x00000177
|
||||
TPMCCECCParameters TPMCC = 0x00000178
|
||||
TPMCCFirmwareRead TPMCC = 0x00000179
|
||||
TPMCCGetCapability TPMCC = 0x0000017A
|
||||
TPMCCGetRandom TPMCC = 0x0000017B
|
||||
TPMCCGetTestResult TPMCC = 0x0000017C
|
||||
TPMCCHash TPMCC = 0x0000017D
|
||||
TPMCCPCRRead TPMCC = 0x0000017E
|
||||
TPMCCPolicyPCR TPMCC = 0x0000017F
|
||||
TPMCCPolicyRestart TPMCC = 0x00000180
|
||||
TPMCCReadClock TPMCC = 0x00000181
|
||||
TPMCCPCRExtend TPMCC = 0x00000182
|
||||
TPMCCPCRSetAuthValue TPMCC = 0x00000183
|
||||
TPMCCNVCertify TPMCC = 0x00000184
|
||||
TPMCCEventSequenceComplete TPMCC = 0x00000185
|
||||
TPMCCHashSequenceStart TPMCC = 0x00000186
|
||||
TPMCCPolicyPhysicalPresence TPMCC = 0x00000187
|
||||
TPMCCPolicyDuplicationSelect TPMCC = 0x00000188
|
||||
TPMCCPolicyGetDigest TPMCC = 0x00000189
|
||||
TPMCCTestParms TPMCC = 0x0000018A
|
||||
TPMCCCommit TPMCC = 0x0000018B
|
||||
TPMCCPolicyPassword TPMCC = 0x0000018C
|
||||
TPMCCZGen2Phase TPMCC = 0x0000018D
|
||||
TPMCCECEphemeral TPMCC = 0x0000018E
|
||||
TPMCCPolicyNvWritten TPMCC = 0x0000018F
|
||||
TPMCCPolicyTemplate TPMCC = 0x00000190
|
||||
TPMCCCreateLoaded TPMCC = 0x00000191
|
||||
TPMCCPolicyAuthorizeNV TPMCC = 0x00000192
|
||||
TPMCCEncryptDecrypt2 TPMCC = 0x00000193
|
||||
TPMCCACGetCapability TPMCC = 0x00000194
|
||||
TPMCCACSend TPMCC = 0x00000195
|
||||
TPMCCPolicyACSendSelect TPMCC = 0x00000196
|
||||
TPMCCCertifyX509 TPMCC = 0x00000197
|
||||
TPMCCACTSetTimeout TPMCC = 0x00000198
|
||||
)
|
||||
|
||||
// TPMRC represents a TPM_RC.
|
||||
// See definition in Part 2: Structures, section 6.6.
|
||||
type TPMRC uint32
|
||||
|
||||
// TPMRC values come from Part 2: Structures, section 6.6.3.
|
||||
const (
|
||||
rcVer1 = 0x00000100
|
||||
rcFmt1 = 0x00000080
|
||||
rcWarn = 0x00000900
|
||||
rcP = 0x00000040
|
||||
rcS = 0x00000800
|
||||
TPMRCSuccess TPMRC = 0x00000000
|
||||
// FMT0 error codes
|
||||
TPMRCInitialize TPMRC = rcVer1 + 0x000
|
||||
TPMRCFailure TPMRC = rcVer1 + 0x001
|
||||
TPMRCSequence TPMRC = rcVer1 + 0x003
|
||||
TPMRCPrivate TPMRC = rcVer1 + 0x00B
|
||||
TPMRCHMAC TPMRC = rcVer1 + 0x019
|
||||
TPMRCDisabled TPMRC = rcVer1 + 0x020
|
||||
TPMRCExclusive TPMRC = rcVer1 + 0x021
|
||||
TPMRCAuthType TPMRC = rcVer1 + 0x024
|
||||
TPMRCAuthMissing TPMRC = rcVer1 + 0x025
|
||||
TPMRCPolicy TPMRC = rcVer1 + 0x026
|
||||
TPMRCPCR TPMRC = rcVer1 + 0x027
|
||||
TPMRCPCRChanged TPMRC = rcVer1 + 0x028
|
||||
TPMRCUpgrade TPMRC = rcVer1 + 0x02D
|
||||
TPMRCTooManyContexts TPMRC = rcVer1 + 0x02E
|
||||
TPMRCAuthUnavailable TPMRC = rcVer1 + 0x02F
|
||||
TPMRCReboot TPMRC = rcVer1 + 0x030
|
||||
TPMRCUnbalanced TPMRC = rcVer1 + 0x031
|
||||
TPMRCCommandSize TPMRC = rcVer1 + 0x042
|
||||
TPMRCCommandCode TPMRC = rcVer1 + 0x043
|
||||
TPMRCAuthSize TPMRC = rcVer1 + 0x044
|
||||
TPMRCAuthContext TPMRC = rcVer1 + 0x045
|
||||
TPMRCNVRange TPMRC = rcVer1 + 0x046
|
||||
TPMRCNVSize TPMRC = rcVer1 + 0x047
|
||||
TPMRCNVLocked TPMRC = rcVer1 + 0x048
|
||||
TPMRCNVAuthorization TPMRC = rcVer1 + 0x049
|
||||
TPMRCNVUninitialized TPMRC = rcVer1 + 0x04A
|
||||
TPMRCNVSpace TPMRC = rcVer1 + 0x04B
|
||||
TPMRCNVDefined TPMRC = rcVer1 + 0x04C
|
||||
TPMRCBadContext TPMRC = rcVer1 + 0x050
|
||||
TPMRCCPHash TPMRC = rcVer1 + 0x051
|
||||
TPMRCParent TPMRC = rcVer1 + 0x052
|
||||
TPMRCNeedsTest TPMRC = rcVer1 + 0x053
|
||||
TPMRCNoResult TPMRC = rcVer1 + 0x054
|
||||
TPMRCSensitive TPMRC = rcVer1 + 0x055
|
||||
// FMT1 error codes
|
||||
TPMRCAsymmetric TPMRC = rcFmt1 + 0x001
|
||||
TPMRCAttributes TPMRC = rcFmt1 + 0x002
|
||||
TPMRCHash TPMRC = rcFmt1 + 0x003
|
||||
TPMRCValue TPMRC = rcFmt1 + 0x004
|
||||
TPMRCHierarchy TPMRC = rcFmt1 + 0x005
|
||||
TPMRCKeySize TPMRC = rcFmt1 + 0x007
|
||||
TPMRCMGF TPMRC = rcFmt1 + 0x008
|
||||
TPMRCMode TPMRC = rcFmt1 + 0x009
|
||||
TPMRCType TPMRC = rcFmt1 + 0x00A
|
||||
TPMRCHandle TPMRC = rcFmt1 + 0x00B
|
||||
TPMRCKDF TPMRC = rcFmt1 + 0x00C
|
||||
TPMRCRange TPMRC = rcFmt1 + 0x00D
|
||||
TPMRCAuthFail TPMRC = rcFmt1 + 0x00E
|
||||
TPMRCNonce TPMRC = rcFmt1 + 0x00F
|
||||
TPMRCPP TPMRC = rcFmt1 + 0x010
|
||||
TPMRCScheme TPMRC = rcFmt1 + 0x012
|
||||
TPMRCSize TPMRC = rcFmt1 + 0x015
|
||||
TPMRCSymmetric TPMRC = rcFmt1 + 0x016
|
||||
TPMRCTag TPMRC = rcFmt1 + 0x017
|
||||
TPMRCSelector TPMRC = rcFmt1 + 0x018
|
||||
TPMRCInsufficient TPMRC = rcFmt1 + 0x01A
|
||||
TPMRCSignature TPMRC = rcFmt1 + 0x01B
|
||||
TPMRCKey TPMRC = rcFmt1 + 0x01C
|
||||
TPMRCPolicyFail TPMRC = rcFmt1 + 0x01D
|
||||
TPMRCIntegrity TPMRC = rcFmt1 + 0x01F
|
||||
TPMRCTicket TPMRC = rcFmt1 + 0x020
|
||||
TPMRCReservedBits TPMRC = rcFmt1 + 0x021
|
||||
TPMRCBadAuth TPMRC = rcFmt1 + 0x022
|
||||
TPMRCExpired TPMRC = rcFmt1 + 0x023
|
||||
TPMRCPolicyCC TPMRC = rcFmt1 + 0x024
|
||||
TPMRCBinding TPMRC = rcFmt1 + 0x025
|
||||
TPMRCCurve TPMRC = rcFmt1 + 0x026
|
||||
TPMRCECCPoint TPMRC = rcFmt1 + 0x027
|
||||
// Warnings
|
||||
TPMRCContextGap TPMRC = rcWarn + 0x001
|
||||
TPMRCObjectMemory TPMRC = rcWarn + 0x002
|
||||
TPMRCSessionMemory TPMRC = rcWarn + 0x003
|
||||
TPMRCMemory TPMRC = rcWarn + 0x004
|
||||
TPMRCSessionHandles TPMRC = rcWarn + 0x005
|
||||
TPMRCObjectHandles TPMRC = rcWarn + 0x006
|
||||
TPMRCLocality TPMRC = rcWarn + 0x007
|
||||
TPMRCYielded TPMRC = rcWarn + 0x008
|
||||
TPMRCCanceled TPMRC = rcWarn + 0x009
|
||||
TPMRCTesting TPMRC = rcWarn + 0x00A
|
||||
TPMRCReferenceH0 TPMRC = rcWarn + 0x010
|
||||
TPMRCReferenceH1 TPMRC = rcWarn + 0x011
|
||||
TPMRCReferenceH2 TPMRC = rcWarn + 0x012
|
||||
TPMRCReferenceH3 TPMRC = rcWarn + 0x013
|
||||
TPMRCReferenceH4 TPMRC = rcWarn + 0x014
|
||||
TPMRCReferenceH5 TPMRC = rcWarn + 0x015
|
||||
TPMRCReferenceH6 TPMRC = rcWarn + 0x016
|
||||
TPMRCReferenceS0 TPMRC = rcWarn + 0x018
|
||||
TPMRCReferenceS1 TPMRC = rcWarn + 0x019
|
||||
TPMRCReferenceS2 TPMRC = rcWarn + 0x01A
|
||||
TPMRCReferenceS3 TPMRC = rcWarn + 0x01B
|
||||
TPMRCReferenceS4 TPMRC = rcWarn + 0x01C
|
||||
TPMRCReferenceS5 TPMRC = rcWarn + 0x01D
|
||||
TPMRCReferenceS6 TPMRC = rcWarn + 0x01E
|
||||
TPMRCNVRate TPMRC = rcWarn + 0x020
|
||||
TPMRCLockout TPMRC = rcWarn + 0x021
|
||||
TPMRCRetry TPMRC = rcWarn + 0x022
|
||||
TPMRCNVUnavailable TPMRC = rcWarn + 0x023
|
||||
)
|
||||
|
||||
// TPMEO represents a TPM_EO.
|
||||
// See definition in Part 2: Structures, section 6.8.
|
||||
type TPMEO uint16
|
||||
|
||||
// TPMEO values come from Part 2: Structures, section 6.8.
|
||||
const (
|
||||
TPMEOEq TPMEO = 0x0000
|
||||
TPMEONeq TPMEO = 0x0001
|
||||
TPMEOSignedGT TPMEO = 0x0002
|
||||
TPMEOUnsignedGT TPMEO = 0x0003
|
||||
TPMEOSignedLT TPMEO = 0x0004
|
||||
TPMEOUnsignedLT TPMEO = 0x0005
|
||||
TPMEOSignedGE TPMEO = 0x0006
|
||||
TPMEOUnsignedGE TPMEO = 0x0007
|
||||
TPMEOSignedLE TPMEO = 0x0008
|
||||
TPMEOUnsignedLE TPMEO = 0x0009
|
||||
TPMEOBitSet TPMEO = 0x000A
|
||||
TPMEOBitClear TPMEO = 0x000B
|
||||
)
|
||||
|
||||
// TPMST represents a TPM_ST.
|
||||
// See definition in Part 2: Structures, section 6.9.
|
||||
type TPMST uint16
|
||||
|
||||
// TPMST values come from Part 2: Structures, section 6.9.
|
||||
const (
|
||||
TPMSTRspCommand TPMST = 0x00C4
|
||||
TPMSTNull TPMST = 0x8000
|
||||
TPMSTNoSessions TPMST = 0x8001
|
||||
TPMSTSessions TPMST = 0x8002
|
||||
TPMSTAttestNV TPMST = 0x8014
|
||||
TPMSTAttestCommandAudit TPMST = 0x8015
|
||||
TPMSTAttestSessionAudit TPMST = 0x8016
|
||||
TPMSTAttestCertify TPMST = 0x8017
|
||||
TPMSTAttestQuote TPMST = 0x8018
|
||||
TPMSTAttestTime TPMST = 0x8019
|
||||
TPMSTAttestCreation TPMST = 0x801A
|
||||
TPMSTAttestNVDigest TPMST = 0x801C
|
||||
TPMSTCreation TPMST = 0x8021
|
||||
TPMSTVerified TPMST = 0x8022
|
||||
TPMSTAuthSecret TPMST = 0x8023
|
||||
TPMSTHashCheck TPMST = 0x8024
|
||||
TPMSTAuthSigned TPMST = 0x8025
|
||||
TPMSTFuManifest TPMST = 0x8029
|
||||
)
|
||||
|
||||
// TPMSU represents a TPM_SU.
|
||||
// See definition in Part 2: Structures, section 6.10.
|
||||
type TPMSU uint16
|
||||
|
||||
// TPMSU values come from Part 2: Structures, section 6.10.
|
||||
const (
|
||||
TPMSUClear TPMSU = 0x0000
|
||||
TPMSUState TPMSU = 0x0001
|
||||
)
|
||||
|
||||
// TPMSE represents a TPM_SE.
|
||||
// See definition in Part 2: Structures, section 6.11.
|
||||
type TPMSE uint8
|
||||
|
||||
// TPMSE values come from Part 2: Structures, section 6.11.
|
||||
const (
|
||||
TPMSEHMAC TPMSE = 0x00
|
||||
TPMSEPolicy TPMSE = 0x01
|
||||
TPMSETrial TPMSE = 0x03
|
||||
)
|
||||
|
||||
// TPMCap represents a TPM_CAP.
|
||||
// See definition in Part 2: Structures, section 6.12.
|
||||
type TPMCap uint32
|
||||
|
||||
// TPMCap values come from Part 2: Structures, section 6.12.
|
||||
const (
|
||||
TPMCapAlgs TPMCap = 0x00000000
|
||||
TPMCapHandles TPMCap = 0x00000001
|
||||
TPMCapCommands TPMCap = 0x00000002
|
||||
TPMCapPPCommands TPMCap = 0x00000003
|
||||
TPMCapAuditCommands TPMCap = 0x00000004
|
||||
TPMCapPCRs TPMCap = 0x00000005
|
||||
TPMCapTPMProperties TPMCap = 0x00000006
|
||||
TPMCapPCRProperties TPMCap = 0x00000007
|
||||
TPMCapECCCurves TPMCap = 0x00000008
|
||||
TPMCapAuthPolicies TPMCap = 0x00000009
|
||||
TPMCapACT TPMCap = 0x0000000A
|
||||
)
|
||||
|
||||
// TPMPT represents a TPM_PT.
|
||||
// See definition in Part 2: Structures, section 6.13.
|
||||
type TPMPT uint32
|
||||
|
||||
// TPMPT values come from Part 2: Structures, section 6.13.
|
||||
const (
|
||||
// a 4-octet character string containing the TPM Family value
|
||||
// (TPM_SPEC_FAMILY)
|
||||
TPMPTFamilyIndicator TPMPT = 0x00000100
|
||||
// the level of the specification
|
||||
TPMPTLevel TPMPT = 0x00000101
|
||||
// the specification Revision times 100
|
||||
TPMPTRevision TPMPT = 0x00000102
|
||||
// the specification day of year using TCG calendar
|
||||
TPMPTDayofYear TPMPT = 0x00000103
|
||||
// the specification year using the CE
|
||||
TPMPTYear TPMPT = 0x00000104
|
||||
// the vendor ID unique to each TPM manufacturer
|
||||
TPMPTManufacturer TPMPT = 0x00000105
|
||||
// the first four characters of the vendor ID string
|
||||
TPMPTVendorString1 TPMPT = 0x00000106
|
||||
// the second four characters of the vendor ID string
|
||||
TPMPTVendorString2 TPMPT = 0x00000107
|
||||
// the third four characters of the vendor ID string
|
||||
TPMPTVendorString3 TPMPT = 0x00000108
|
||||
// the fourth four characters of the vendor ID sting
|
||||
TPMPTVendorString4 TPMPT = 0x00000109
|
||||
// vendor-defined value indicating the TPM model
|
||||
TPMPTVendorTPMType TPMPT = 0x0000010A
|
||||
// the most-significant 32 bits of a TPM vendor-specific value
|
||||
// indicating the version number of the firmware.
|
||||
TPMPTFirmwareVersion1 TPMPT = 0x0000010B
|
||||
// the least-significant 32 bits of a TPM vendor-specific value
|
||||
// indicating the version number of the firmware.
|
||||
TPMPTFirmwareVersion2 TPMPT = 0x0000010C
|
||||
// the maximum size of a parameter TPM2B_MAX_BUFFER)
|
||||
TPMPTInputBuffer TPMPT = 0x0000010D
|
||||
// the minimum number of transient objects that can be held in TPM RAM
|
||||
TPMPTHRTransientMin TPMPT = 0x0000010E
|
||||
// the minimum number of persistent objects that can be held in TPM NV
|
||||
// memory
|
||||
TPMPTHRPersistentMin TPMPT = 0x0000010F
|
||||
// the minimum number of authorization sessions that can be held in TPM
|
||||
// RAM
|
||||
TPMPTHRLoadedMin TPMPT = 0x00000110
|
||||
// the number of authorization sessions that may be active at a time
|
||||
TPMPTActiveSessionsMax TPMPT = 0x00000111
|
||||
// the number of PCR implemented
|
||||
TPMPTPCRCount TPMPT = 0x00000112
|
||||
// the minimum number of octets in a TPMS_PCR_SELECT.sizeOfSelect
|
||||
TPMPTPCRSelectMin TPMPT = 0x00000113
|
||||
// the maximum allowed difference (unsigned) between the contextID
|
||||
// values of two saved session contexts
|
||||
TPMPTContextGapMax TPMPT = 0x00000114
|
||||
// the maximum number of NV Indexes that are allowed to have the
|
||||
// TPM_NT_COUNTER attribute
|
||||
TPMPTNVCountersMax TPMPT = 0x00000116
|
||||
// the maximum size of an NV Index data area
|
||||
TPMPTNVIndexMax TPMPT = 0x00000117
|
||||
// a TPMA_MEMORY indicating the memory management method for the TPM
|
||||
TPMPTMemory TPMPT = 0x00000118
|
||||
// interval, in milliseconds, between updates to the copy of
|
||||
// TPMS_CLOCK_INFO.clock in NV
|
||||
TPMPTClockUpdate TPMPT = 0x00000119
|
||||
// the algorithm used for the integrity HMAC on saved contexts and for
|
||||
// hashing the fuData of TPM2_FirmwareRead()
|
||||
TPMPTContextHash TPMPT = 0x0000011A
|
||||
// TPM_ALG_ID, the algorithm used for encryption of saved contexts
|
||||
TPMPTContextSym TPMPT = 0x0000011B
|
||||
// TPM_KEY_BITS, the size of the key used for encryption of saved
|
||||
// contexts
|
||||
TPMPTContextSymSize TPMPT = 0x0000011C
|
||||
// the modulus - 1 of the count for NV update of an orderly counter
|
||||
TPMPTOrderlyCount TPMPT = 0x0000011D
|
||||
// the maximum value for commandSize in a command
|
||||
TPMPTMaxCommandSize TPMPT = 0x0000011E
|
||||
// the maximum value for responseSize in a response
|
||||
TPMPTMaxResponseSize TPMPT = 0x0000011F
|
||||
// the maximum size of a digest that can be produced by the TPM
|
||||
TPMPTMaxDigest TPMPT = 0x00000120
|
||||
// the maximum size of an object context that will be returned by
|
||||
// TPM2_ContextSave
|
||||
TPMPTMaxObjectContext TPMPT = 0x00000121
|
||||
// the maximum size of a session context that will be returned by
|
||||
// TPM2_ContextSave
|
||||
TPMPTMaxSessionContext TPMPT = 0x00000122
|
||||
// platform-specific family (a TPM_PS value)(see Table 25)
|
||||
TPMPTPSFamilyIndicator TPMPT = 0x00000123
|
||||
// the level of the platform-specific specification
|
||||
TPMPTPSLevel TPMPT = 0x00000124
|
||||
// a platform specific value
|
||||
TPMPTPSRevision TPMPT = 0x00000125
|
||||
// the platform-specific TPM specification day of year using TCG
|
||||
// calendar
|
||||
TPMPTPSDayOfYear TPMPT = 0x00000126
|
||||
// the platform-specific TPM specification year using the CE
|
||||
TPMPTPSYear TPMPT = 0x00000127
|
||||
// the number of split signing operations supported by the TPM
|
||||
TPMPTSplitMax TPMPT = 0x00000128
|
||||
// total number of commands implemented in the TPM
|
||||
TPMPTTotalCommands TPMPT = 0x00000129
|
||||
// number of commands from the TPM library that are implemented
|
||||
TPMPTLibraryCommands TPMPT = 0x0000012A
|
||||
// number of vendor commands that are implemented
|
||||
TPMPTVendorCommands TPMPT = 0x0000012B
|
||||
// the maximum data size in one NV write, NV read, NV extend, or NV
|
||||
// certify command
|
||||
TPMPTNVBufferMax TPMPT = 0x0000012C
|
||||
// a TPMA_MODES value, indicating that the TPM is designed for these
|
||||
// modes.
|
||||
TPMPTModes TPMPT = 0x0000012D
|
||||
// the maximum size of a TPMS_CAPABILITY_DATA structure returned in
|
||||
// TPM2_GetCapability().
|
||||
TPMPTMaxCapBuffer TPMPT = 0x0000012E
|
||||
// TPMA_PERMANENT
|
||||
TPMPTPermanent TPMPT = 0x00000200
|
||||
// TPMA_STARTUP_CLEAR
|
||||
TPMPTStartupClear TPMPT = 0x00000201
|
||||
// the number of NV Indexes currently defined
|
||||
TPMPTHRNVIndex TPMPT = 0x00000202
|
||||
// the number of authorization sessions currently loaded into TPM RAM
|
||||
TPMPTHRLoaded TPMPT = 0x00000203
|
||||
// the number of additional authorization sessions, of any type, that
|
||||
// could be loaded into TPM RAM
|
||||
TPMPTHRLoadedAvail TPMPT = 0x00000204
|
||||
// the number of active authorization sessions currently being tracked
|
||||
// by the TPM
|
||||
TPMPTHRActive TPMPT = 0x00000205
|
||||
// the number of additional authorization sessions, of any type, that
|
||||
// could be created
|
||||
TPMPTHRActiveAvail TPMPT = 0x00000206
|
||||
// estimate of the number of additional transient objects that could be
|
||||
// loaded into TPM RAM
|
||||
TPMPTHRTransientAvail TPMPT = 0x00000207
|
||||
// the number of persistent objects currently loaded into TPM NV memory
|
||||
TPMPTHRPersistent TPMPT = 0x00000208
|
||||
// the number of additional persistent objects that could be loaded into
|
||||
// NV memory
|
||||
TPMPTHRPersistentAvail TPMPT = 0x00000209
|
||||
// the number of defined NV Indexes that have NV the TPM_NT_COUNTER
|
||||
// attribute
|
||||
TPMPTNVCounters TPMPT = 0x0000020A
|
||||
// the number of additional NV Indexes that can be defined with their
|
||||
// TPM_NT of TPM_NV_COUNTER and the TPMA_NV_ORDERLY attribute SET
|
||||
TPMPTNVCountersAvail TPMPT = 0x0000020B
|
||||
// code that limits the algorithms that may be used with the TPM
|
||||
TPMPTAlgorithmSet TPMPT = 0x0000020C
|
||||
// the number of loaded ECC curves
|
||||
TPMPTLoadedCurves TPMPT = 0x0000020D
|
||||
// the current value of the lockout counter (failedTries)
|
||||
TPMPTLockoutCounter TPMPT = 0x0000020E
|
||||
// the number of authorization failures before DA lockout is invoked
|
||||
TPMPTMaxAuthFail TPMPT = 0x0000020F
|
||||
// the number of seconds before the value reported by
|
||||
// TPM_PT_LOCKOUT_COUNTER is decremented
|
||||
TPMPTLockoutInterval TPMPT = 0x00000210
|
||||
// the number of seconds after a lockoutAuth failure before use of
|
||||
// lockoutAuth may be attempted again
|
||||
TPMPTLockoutRecovery TPMPT = 0x00000211
|
||||
// number of milliseconds before the TPM will accept another command
|
||||
// that will modify NV
|
||||
TPMPTNVWriteRecovery TPMPT = 0x00000212
|
||||
// the high-order 32 bits of the command audit counter
|
||||
TPMPTAuditCounter0 TPMPT = 0x00000213
|
||||
// the low-order 32 bits of the command audit counter
|
||||
TPMPTAuditCounter1 TPMPT = 0x00000214
|
||||
)
|
||||
|
||||
// TPMPTPCR represents a TPM_PT_PCR.
|
||||
// See definition in Part 2: Structures, section 6.14.
|
||||
type TPMPTPCR uint32
|
||||
|
||||
// TPMPTPCR values come from Part 2: Structures, section 6.14.
|
||||
const (
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR is saved and
|
||||
// restored by TPM_SU_STATE
|
||||
TPMPTPCRSave TPMPTPCR = 0x00000000
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be
|
||||
// extended from locality 0
|
||||
TPMPTPCRExtendL0 TPMPTPCR = 0x00000001
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset
|
||||
// by TPM2_PCR_Reset() from locality 0
|
||||
TPMPTPCRResetL0 TPMPTPCR = 0x00000002
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be
|
||||
// extended from locality 1
|
||||
TPMPTPCRExtendL1 TPMPTPCR = 0x00000003
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset
|
||||
// by TPM2_PCR_Reset() from locality 1
|
||||
TPMPTPCRResetL1 TPMPTPCR = 0x00000004
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be
|
||||
// extended from locality 2
|
||||
TPMPTPCRExtendL2 TPMPTPCR = 0x00000005
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset
|
||||
// by TPM2_PCR_Reset() from locality 2
|
||||
TPMPTPCRResetL2 TPMPTPCR = 0x00000006
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be
|
||||
// extended from locality 3
|
||||
TPMPTPCRExtendL3 TPMPTPCR = 0x00000007
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset
|
||||
// by TPM2_PCR_Reset() from locality 3
|
||||
TPMPTPCRResetL3 TPMPTPCR = 0x00000008
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be
|
||||
// extended from locality 4
|
||||
TPMPTPCRExtendL4 TPMPTPCR = 0x00000009
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset
|
||||
// by TPM2_PCR_Reset() from locality 4
|
||||
TPMPTPCRResetL4 TPMPTPCR = 0x0000000A
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that modifications to this
|
||||
// PCR (reset or Extend) will not increment the pcrUpdateCounter
|
||||
TPMPTPCRNoIncrement TPMPTPCR = 0x00000011
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR is reset by a
|
||||
// D-RTM event
|
||||
TPMPTPCRDRTMRest TPMPTPCR = 0x00000012
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled
|
||||
// by policy
|
||||
TPMPTPCRPolicy TPMPTPCR = 0x00000013
|
||||
// a SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled
|
||||
// by an authorization value
|
||||
TPMPTPCRAuth TPMPTPCR = 0x00000014
|
||||
)
|
||||
|
||||
// TPMHT represents a TPM_HT.
|
||||
// See definition in Part 2: Structures, section 7.2.
|
||||
type TPMHT uint8
|
||||
|
||||
// TPMHT values come from Part 2: Structures, section 7.2.
|
||||
const (
|
||||
TPMHTPCR TPMHT = 0x00
|
||||
TPMHTNVIndex TPMHT = 0x01
|
||||
TPMHTHMACSession TPMHT = 0x02
|
||||
TPMHTPolicySession TPMHT = 0x03
|
||||
TPMHTPermanent TPMHT = 0x40
|
||||
TPMHTTransient TPMHT = 0x80
|
||||
TPMHTPersistent TPMHT = 0x81
|
||||
TPMHTAC TPMHT = 0x90
|
||||
)
|
||||
|
||||
// Saved Context transient object handles.
|
||||
// See definition in Part 2: Structures, section 14.6.2
|
||||
// Context Handle Values come from table 211
|
||||
const (
|
||||
// an ordinary transient object
|
||||
TPMIDHSavedTransient TPMIDHSaved = 0x80000000
|
||||
// a sequence object
|
||||
TPMIDHSavedSequence TPMIDHSaved = 0x80000001
|
||||
// a transient object with the stClear attribute SET
|
||||
TPMIDHSavedTransientClear TPMIDHSaved = 0x80000002
|
||||
)
|
||||
|
||||
// TPMHandle represents a TPM_HANDLE.
|
||||
// See definition in Part 2: Structures, section 7.1.
|
||||
type TPMHandle uint32
|
||||
|
||||
// TPMHandle values come from Part 2: Structures, section 7.4.
|
||||
const (
|
||||
TPMRHOwner TPMHandle = 0x40000001
|
||||
TPMRHNull TPMHandle = 0x40000007
|
||||
TPMRSPW TPMHandle = 0x40000009
|
||||
TPMRHLockout TPMHandle = 0x4000000A
|
||||
TPMRHEndorsement TPMHandle = 0x4000000B
|
||||
TPMRHPlatform TPMHandle = 0x4000000C
|
||||
TPMRHPlatformNV TPMHandle = 0x4000000D
|
||||
TPMRHFWOwner TPMHandle = 0x40000140
|
||||
TPMRHFWEndorsement TPMHandle = 0x40000141
|
||||
TPMRHFWPlatform TPMHandle = 0x40000142
|
||||
TPMRHFWNull TPMHandle = 0x40000143
|
||||
)
|
||||
|
||||
// TPMNT represents a TPM_NT.
|
||||
// See definition in Part 2: Structures, section 13.4.
|
||||
type TPMNT uint8
|
||||
|
||||
// TPMNT values come from Part 2: Structures, section 13.2.
|
||||
const (
|
||||
// contains data that is opaque to the TPM that can only be modified
|
||||
// using TPM2_NV_Write().
|
||||
TPMNTOrdinary TPMNT = 0x0
|
||||
// contains an 8-octet value that is to be used as a counter and can
|
||||
// only be modified with TPM2_NV_Increment()
|
||||
TPMNTCounter TPMNT = 0x1
|
||||
// contains an 8-octet value to be used as a bit field and can only be
|
||||
// modified with TPM2_NV_SetBits().
|
||||
TPMNTBits TPMNT = 0x2
|
||||
// contains a digest-sized value used like a PCR. The Index can only be
|
||||
// modified using TPM2_NV_Extend(). The extend will use the nameAlg of
|
||||
// the Index.
|
||||
TPMNTExtend TPMNT = 0x4
|
||||
// contains pinCount that increments on a PIN authorization failure and
|
||||
// a pinLimit
|
||||
TPMNTPinFail TPMNT = 0x8
|
||||
// contains pinCount that increments on a PIN authorization success and
|
||||
// a pinLimit
|
||||
TPMNTPinPass TPMNT = 0x9
|
||||
)
|
||||
14
vendor/github.com/google/go-tpm/tpm2/constants_internal.go
generated
vendored
Normal file
14
vendor/github.com/google/go-tpm/tpm2/constants_internal.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package tpm2
|
||||
|
||||
// This file contains constant definitions we don't want to use stringer with
|
||||
// (because they are duplicates of other values, and we would prefer those values
|
||||
// to influence the string representations).
|
||||
|
||||
// Hash algorithm IDs and command codes that got re-used.
|
||||
const (
|
||||
TPMAlgSHA = TPMAlgSHA1
|
||||
TPMCCHMAC = TPMCCMAC
|
||||
TPMCCHMACStart = TPMCCMACStart
|
||||
TPMHTLoadedSession = TPMHTHMACSession
|
||||
TPMHTSavedSession = TPMHTPolicySession
|
||||
)
|
||||
40
vendor/github.com/google/go-tpm/tpm2/create_credential.go
generated
vendored
Normal file
40
vendor/github.com/google/go-tpm/tpm2/create_credential.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
labelIdentity = "IDENTITY"
|
||||
)
|
||||
|
||||
// CreateCredential creates an encrypted secret that can be recovered using ActivateCredential as part of a key-attestation flow.
|
||||
func CreateCredential(rand io.Reader, pub LabeledEncapsulationKey, name []byte, credentialValue []byte) (idObject []byte, encSecret []byte, err error) {
|
||||
secret, ciphertext, err := pub.Encapsulate(rand, labelIdentity)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Marshal the credentialValue as a TPM2B_DIGEST before encrypting it.
|
||||
// See Part 1, "Credential Protection", and Part 2, "TPMS_ID_OBJECT".
|
||||
credential2B := Marshal(TPM2BDigest{Buffer: credentialValue})
|
||||
|
||||
// Encrypt the credentialValue as encIdentity.
|
||||
encIdentity, err := deriveAndEncrypt(pub, secret, name, credential2B)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Compute the HMAC of (encIdentity || name)
|
||||
identityHMAC, err := deriveAndHMAC(pub, secret, nil, encIdentity, name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Marshal the virtual TPMS_ID_OBJECT ourselves. We have to do this since encIdentity's size is encrypted.
|
||||
idObject = make([]byte, 0, 2+len(identityHMAC)+len(encIdentity))
|
||||
idObject = append(idObject, Marshal(TPM2BDigest{Buffer: identityHMAC})...)
|
||||
idObject = append(idObject, encIdentity...)
|
||||
|
||||
return idObject, ciphertext, nil
|
||||
}
|
||||
41
vendor/github.com/google/go-tpm/tpm2/create_duplicate.go
generated
vendored
Normal file
41
vendor/github.com/google/go-tpm/tpm2/create_duplicate.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
labelDuplicate = "DUPLICATE"
|
||||
)
|
||||
|
||||
// CreateDuplicate encrypts an object so that it can be imported under a target Storage Key.
|
||||
// An inner wrapper is not supported.
|
||||
func CreateDuplicate(rand io.Reader, pub LabeledEncapsulationKey, name []byte, sensitive []byte) (duplicate []byte, encSecret []byte, err error) {
|
||||
secret, ciphertext, err := pub.Encapsulate(rand, labelDuplicate)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Marshal the sensitive as a TPM2B_SENSITIVE before encrypting it.
|
||||
// See Part 1, "Outer Duplication Wrapper"
|
||||
sensitive2B := Marshal(TPM2BDigest{Buffer: sensitive})
|
||||
|
||||
// Encrypt the sensitive2B as dupSensitive.
|
||||
dupSensitive, err := deriveAndEncrypt(pub, secret, name, sensitive2B)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Compute the HMAC of (dupSensitive || name)
|
||||
outerHMAC, err := deriveAndHMAC(pub, secret, nil, dupSensitive, name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Marshal the virtual _PRIVATE ourselves. We have to do this since dupSensitive's size is encrypted.
|
||||
duplicate = make([]byte, 0, 2+len(outerHMAC)+len(dupSensitive))
|
||||
duplicate = append(duplicate, Marshal(TPM2BDigest{Buffer: outerHMAC})...)
|
||||
duplicate = append(duplicate, dupSensitive...)
|
||||
|
||||
return duplicate, ciphertext, nil
|
||||
}
|
||||
14
vendor/github.com/google/go-tpm/tpm2/create_salt.go
generated
vendored
Normal file
14
vendor/github.com/google/go-tpm/tpm2/create_salt.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package tpm2
|
||||
|
||||
import "io"
|
||||
|
||||
var (
|
||||
labelSecret = "SECRET"
|
||||
)
|
||||
|
||||
// CreateEncryptedSalt encrypts a random salt for secure session establishment.
|
||||
func CreateEncryptedSalt(rand io.Reader, pub LabeledEncapsulationKey) (salt []byte, encSecret []byte, err error) {
|
||||
// The salt value is directly used from the Labeled Key Encapsulation operation.
|
||||
// See Part 1, "Salted and Bound Session Key Generation"
|
||||
return pub.Encapsulate(rand, labelSecret)
|
||||
}
|
||||
193
vendor/github.com/google/go-tpm/tpm2/crypto.go
generated
vendored
Normal file
193
vendor/github.com/google/go-tpm/tpm2/crypto.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdh"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// Priv converts a TPM private key into one recognized by the crypto package.
|
||||
func Priv(public TPMTPublic, sensitive TPMTSensitive) (crypto.PrivateKey, error) {
|
||||
|
||||
var privateKey crypto.PrivateKey
|
||||
|
||||
publicKey, err := Pub(public)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch public.Type {
|
||||
case TPMAlgRSA:
|
||||
publicKey := publicKey.(*rsa.PublicKey)
|
||||
|
||||
if sensitive.SensitiveType != TPMAlgRSA {
|
||||
return nil, fmt.Errorf("sensitive type is not equal to public type")
|
||||
}
|
||||
|
||||
prime, err := sensitive.Sensitive.RSA()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve the RSA prime number")
|
||||
}
|
||||
|
||||
P := new(big.Int).SetBytes(prime.Buffer)
|
||||
Q := new(big.Int).Div(publicKey.N, P)
|
||||
phiN := new(big.Int).Mul(new(big.Int).Sub(P, big.NewInt(1)), new(big.Int).Sub(Q, big.NewInt(1)))
|
||||
D := new(big.Int).ModInverse(big.NewInt(int64(publicKey.E)), phiN)
|
||||
|
||||
rsaKey := &rsa.PrivateKey{
|
||||
PublicKey: *publicKey,
|
||||
D: D,
|
||||
Primes: []*big.Int{P, Q},
|
||||
}
|
||||
rsaKey.Precompute()
|
||||
|
||||
privateKey = rsaKey
|
||||
case TPMAlgECC:
|
||||
publicKey := publicKey.(*ecdsa.PublicKey)
|
||||
|
||||
if sensitive.SensitiveType != TPMAlgECC {
|
||||
return nil, fmt.Errorf("sensitive type is not equal to public type")
|
||||
}
|
||||
|
||||
d, err := sensitive.Sensitive.ECC()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve the ECC")
|
||||
}
|
||||
|
||||
D := new(big.Int).SetBytes(d.Buffer)
|
||||
|
||||
ecdsaKey := &ecdsa.PrivateKey{
|
||||
PublicKey: *publicKey,
|
||||
D: D,
|
||||
}
|
||||
|
||||
privateKey = ecdsaKey
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported public key type: %v", public.Type)
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
// Pub converts a TPM public key into one recognized by the crypto package.
|
||||
func Pub(public TPMTPublic) (crypto.PublicKey, error) {
|
||||
var publicKey crypto.PublicKey
|
||||
|
||||
switch public.Type {
|
||||
case TPMAlgRSA:
|
||||
parameters, err := public.Parameters.RSADetail()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve the RSA parameters")
|
||||
}
|
||||
|
||||
n, err := public.Unique.RSA()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse and retrieve the RSA modulus")
|
||||
}
|
||||
|
||||
publicKey, err = RSAPub(parameters, n)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve the RSA public key")
|
||||
}
|
||||
case TPMAlgECC:
|
||||
parameters, err := public.Parameters.ECCDetail()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve the ECC parameters")
|
||||
}
|
||||
|
||||
pub, err := public.Unique.ECC()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse and retrieve the ECC point")
|
||||
}
|
||||
|
||||
publicKey, err = ECDSAPub(parameters, pub)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve the ECC public key")
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported public key type: %v", public.Type)
|
||||
}
|
||||
|
||||
return publicKey, nil
|
||||
}
|
||||
|
||||
// RSAPub converts a TPM RSA public key into one recognized by the rsa package.
|
||||
func RSAPub(parms *TPMSRSAParms, pub *TPM2BPublicKeyRSA) (*rsa.PublicKey, error) {
|
||||
result := rsa.PublicKey{
|
||||
N: big.NewInt(0).SetBytes(pub.Buffer),
|
||||
E: int(parms.Exponent),
|
||||
}
|
||||
// TPM considers 65537 to be the default RSA public exponent, and 0 in
|
||||
// the parms
|
||||
// indicates so.
|
||||
if result.E == 0 {
|
||||
result.E = 65537
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// ECDSAPub converts a TPM ECC public key into one recognized by the ecdh package
|
||||
func ECDSAPub(parms *TPMSECCParms, pub *TPMSECCPoint) (*ecdsa.PublicKey, error) {
|
||||
|
||||
var c elliptic.Curve
|
||||
switch parms.CurveID {
|
||||
case TPMECCNistP256:
|
||||
c = elliptic.P256()
|
||||
case TPMECCNistP384:
|
||||
c = elliptic.P384()
|
||||
case TPMECCNistP521:
|
||||
c = elliptic.P521()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown curve: %v", parms.CurveID)
|
||||
}
|
||||
|
||||
pubKey := ecdsa.PublicKey{
|
||||
Curve: c,
|
||||
X: big.NewInt(0).SetBytes(pub.X.Buffer),
|
||||
Y: big.NewInt(0).SetBytes(pub.Y.Buffer),
|
||||
}
|
||||
|
||||
return &pubKey, nil
|
||||
}
|
||||
|
||||
// ECDHPub converts a TPM ECC public key into one recognized by the ecdh package
|
||||
func ECDHPub(parms *TPMSECCParms, pub *TPMSECCPoint) (*ecdh.PublicKey, error) {
|
||||
|
||||
pubKey, err := ECDSAPub(parms, pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pubKey.ECDH()
|
||||
}
|
||||
|
||||
// ECCPoint returns an uncompressed ECC Point
|
||||
func ECCPoint(pubKey *ecdh.PublicKey) (*big.Int, *big.Int, error) {
|
||||
b := pubKey.Bytes()
|
||||
size, err := elementLength(pubKey.Curve())
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("ECCPoint: %w", err)
|
||||
}
|
||||
return big.NewInt(0).SetBytes(b[1 : size+1]),
|
||||
big.NewInt(0).SetBytes(b[size+1:]), nil
|
||||
}
|
||||
|
||||
func elementLength(c ecdh.Curve) (int, error) {
|
||||
switch c {
|
||||
case ecdh.P256():
|
||||
// crypto/internal/nistec/fiat.p256ElementLen
|
||||
return 32, nil
|
||||
case ecdh.P384():
|
||||
// crypto/internal/nistec/fiat.p384ElementLen
|
||||
return 48, nil
|
||||
case ecdh.P521():
|
||||
// crypto/internal/nistec/fiat.p521ElementLen
|
||||
return 66, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown element length for curve: %v", c)
|
||||
}
|
||||
}
|
||||
561
vendor/github.com/google/go-tpm/tpm2/errors.go
generated
vendored
Normal file
561
vendor/github.com/google/go-tpm/tpm2/errors.go
generated
vendored
Normal file
@@ -0,0 +1,561 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type errorDesc struct {
|
||||
name string
|
||||
description string
|
||||
}
|
||||
|
||||
var fmt0Descs = map[TPMRC]errorDesc{
|
||||
TPMRCInitialize: {
|
||||
name: "TPM_RC_INITIALIZE",
|
||||
description: "TPM not initialized by TPM2_Startup or already initialized",
|
||||
},
|
||||
TPMRCFailure: {
|
||||
name: "TPM_RC_FAILURE",
|
||||
description: "commands not being accepted because of a TPM failure",
|
||||
},
|
||||
TPMRCSequence: {
|
||||
name: "TPM_RC_SEQUENCE",
|
||||
description: "improper use of a sequence handle",
|
||||
},
|
||||
TPMRCPrivate: {
|
||||
name: "TPM_RC_PRIVATE",
|
||||
description: "not currently used",
|
||||
},
|
||||
TPMRCHMAC: {
|
||||
name: "TPM_RC_HMAC",
|
||||
description: "not currently used",
|
||||
},
|
||||
TPMRCDisabled: {
|
||||
name: "TPM_RC_DISABLED",
|
||||
description: "the command is disabled",
|
||||
},
|
||||
TPMRCExclusive: {
|
||||
name: "TPM_RC_EXCLUSIVE",
|
||||
description: "command failed because audit sequence required exclusivity",
|
||||
},
|
||||
TPMRCAuthType: {
|
||||
name: "TPM_RC_AUTH_TYPE",
|
||||
description: "authorization handle is not correct for command",
|
||||
},
|
||||
TPMRCAuthMissing: {
|
||||
name: "TPM_RC_AUTH_MISSING",
|
||||
description: "command requires an authorization session for handle and it is not present.",
|
||||
},
|
||||
TPMRCPolicy: {
|
||||
name: "TPM_RC_POLICY",
|
||||
description: "policy failure in math operation or an invalid authPolicy value",
|
||||
},
|
||||
TPMRCPCR: {
|
||||
name: "TPM_RC_PCR",
|
||||
description: "PCR check fail",
|
||||
},
|
||||
TPMRCPCRChanged: {
|
||||
name: "TPM_RC_PCR_CHANGED",
|
||||
description: "PCR have changed since checked.",
|
||||
},
|
||||
TPMRCUpgrade: {
|
||||
name: "TPM_RC_UPGRADE",
|
||||
description: "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",
|
||||
},
|
||||
TPMRCTooManyContexts: {
|
||||
name: "TPM_RC_TOO_MANY_CONTEXTS",
|
||||
description: "context ID counter is at maximum.",
|
||||
},
|
||||
TPMRCAuthUnavailable: {
|
||||
name: "TPM_RC_AUTH_UNAVAILABLE",
|
||||
description: "authValue or authPolicy is not available for selected entity.",
|
||||
},
|
||||
TPMRCReboot: {
|
||||
name: "TPM_RC_REBOOT",
|
||||
description: "a _TPM_Init and Startup(CLEAR) is required before the TPM can resume operation.",
|
||||
},
|
||||
TPMRCUnbalanced: {
|
||||
name: "TPM_RC_UNBALANCED",
|
||||
description: "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.",
|
||||
},
|
||||
TPMRCCommandSize: {
|
||||
name: "TPM_RC_COMMAND_SIZE",
|
||||
description: "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",
|
||||
},
|
||||
TPMRCCommandCode: {
|
||||
name: "TPM_RC_COMMAND_CODE",
|
||||
description: "command code not supported",
|
||||
},
|
||||
TPMRCAuthSize: {
|
||||
name: "TPM_RC_AUTHSIZE",
|
||||
description: "the value of authorizationSize is out of range or the number of octets in the Authorization Area is greater than required",
|
||||
},
|
||||
TPMRCAuthContext: {
|
||||
name: "TPM_RC_AUTH_CONTEXT",
|
||||
description: "use of an authorization session with a context command or another command that cannot have an authorization session.",
|
||||
},
|
||||
TPMRCNVRange: {
|
||||
name: "TPM_RC_NV_RANGE",
|
||||
description: "NV offset+size is out of range.",
|
||||
},
|
||||
TPMRCNVSize: {
|
||||
name: "TPM_RC_NV_SIZE",
|
||||
description: "Requested allocation size is larger than allowed.",
|
||||
},
|
||||
TPMRCNVLocked: {
|
||||
name: "TPM_RC_NV_LOCKED",
|
||||
description: "NV access locked.",
|
||||
},
|
||||
TPMRCNVAuthorization: {
|
||||
name: "TPM_RC_NV_AUTHORIZATION",
|
||||
description: "NV access authorization fails in command actions (this failure does not affect lockout.action)",
|
||||
},
|
||||
TPMRCNVUninitialized: {
|
||||
name: "TPM_RC_NV_UNINITIALIZED",
|
||||
description: "an NV Index is used before being initialized or the state saved by TPM2_Shutdown(STATE) could not be restored",
|
||||
},
|
||||
TPMRCNVSpace: {
|
||||
name: "TPM_RC_NV_SPACE",
|
||||
description: "insufficient space for NV allocation",
|
||||
},
|
||||
TPMRCNVDefined: {
|
||||
name: "TPM_RC_NV_DEFINED",
|
||||
description: "NV Index or persistent object already defined",
|
||||
},
|
||||
TPMRCBadContext: {
|
||||
name: "TPM_RC_BAD_CONTEXT",
|
||||
description: "context in TPM2_ContextLoad() is not valid",
|
||||
},
|
||||
TPMRCCPHash: {
|
||||
name: "TPM_RC_CPHASH",
|
||||
description: "cpHash value already set or not correct for use",
|
||||
},
|
||||
TPMRCParent: {
|
||||
name: "TPM_RC_PARENT",
|
||||
description: "handle for parent is not a valid parent",
|
||||
},
|
||||
TPMRCNeedsTest: {
|
||||
name: "TPM_RC_NEEDS_TEST",
|
||||
description: "some function needs testing.",
|
||||
},
|
||||
TPMRCNoResult: {
|
||||
name: "TPM_RC_NO_RESULT",
|
||||
description: "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.",
|
||||
},
|
||||
TPMRCSensitive: {
|
||||
name: "TPM_RC_SENSITIVE",
|
||||
description: "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",
|
||||
},
|
||||
}
|
||||
|
||||
var fmt1Descs = map[TPMRC]errorDesc{
|
||||
TPMRCAsymmetric: {
|
||||
name: "TPM_RC_ASYMMETRIC RC_FMT1",
|
||||
description: "asymmetric algorithm not supported or not correct",
|
||||
},
|
||||
TPMRCAttributes: {
|
||||
name: "TPM_RC_ATTRIBUTES",
|
||||
description: "inconsistent attributes",
|
||||
},
|
||||
TPMRCHash: {
|
||||
name: "TPM_RC_HASH",
|
||||
description: "hash algorithm not supported or not appropriate",
|
||||
},
|
||||
TPMRCValue: {
|
||||
name: "TPM_RC_VALUE",
|
||||
description: "value is out of range or is not correct for the context",
|
||||
},
|
||||
TPMRCHierarchy: {
|
||||
name: "TPM_RC_HIERARCHY",
|
||||
description: "hierarchy is not enabled or is not correct for the use",
|
||||
},
|
||||
TPMRCKeySize: {
|
||||
name: "TPM_RC_KEY_SIZE",
|
||||
description: "key size is not supported",
|
||||
},
|
||||
TPMRCMGF: {
|
||||
name: "TPM_RC_MGF",
|
||||
description: "mask generation function not supported",
|
||||
},
|
||||
TPMRCMode: {
|
||||
name: "TPM_RC_MODE",
|
||||
description: "mode of operation not supported",
|
||||
},
|
||||
TPMRCType: {
|
||||
name: "TPM_RC_TYPE",
|
||||
description: "the type of the value is not appropriate for the use",
|
||||
},
|
||||
TPMRCHandle: {
|
||||
name: "TPM_RC_HANDLE",
|
||||
description: "the handle is not correct for the use",
|
||||
},
|
||||
TPMRCKDF: {
|
||||
name: "TPM_RC_KDF",
|
||||
description: "unsupported key derivation function or function not appropriate for use",
|
||||
},
|
||||
TPMRCRange: {
|
||||
name: "TPM_RC_RANGE",
|
||||
description: "value was out of allowed range.",
|
||||
},
|
||||
TPMRCAuthFail: {
|
||||
name: "TPM_RC_AUTH_FAIL",
|
||||
description: "the authorization HMAC check failed and DA counter incremented",
|
||||
},
|
||||
TPMRCNonce: {
|
||||
name: "TPM_RC_NONCE",
|
||||
description: "invalid nonce size or nonce value mismatch",
|
||||
},
|
||||
TPMRCPP: {
|
||||
name: "TPM_RC_PP",
|
||||
description: "authorization requires assertion of PP",
|
||||
},
|
||||
TPMRCScheme: {
|
||||
name: "TPM_RC_SCHEME",
|
||||
description: "unsupported or incompatible scheme",
|
||||
},
|
||||
TPMRCSize: {
|
||||
name: "TPM_RC_SIZE",
|
||||
description: "structure is the wrong size",
|
||||
},
|
||||
TPMRCSymmetric: {
|
||||
name: "TPM_RC_SYMMETRIC",
|
||||
description: "unsupported symmetric algorithm or key size, or not appropriate for instance",
|
||||
},
|
||||
TPMRCTag: {
|
||||
name: "TPM_RC_TAG",
|
||||
description: "incorrect structure tag",
|
||||
},
|
||||
TPMRCSelector: {
|
||||
name: "TPM_RC_SELECTOR",
|
||||
description: "union selector is incorrect",
|
||||
},
|
||||
TPMRCInsufficient: {
|
||||
name: "TPM_RC_INSUFFICIENT",
|
||||
description: "the TPM was unable to unmarshal a value because there were not enough octets in the input buffer",
|
||||
},
|
||||
TPMRCSignature: {
|
||||
name: "TPM_RC_SIGNATURE",
|
||||
description: "the signature is not valid",
|
||||
},
|
||||
TPMRCKey: {
|
||||
name: "TPM_RC_KEY",
|
||||
description: "key fields are not compatible with the selected use",
|
||||
},
|
||||
TPMRCPolicyFail: {
|
||||
name: "TPM_RC_POLICY_FAIL",
|
||||
description: "a policy check failed",
|
||||
},
|
||||
TPMRCIntegrity: {
|
||||
name: "TPM_RC_INTEGRITY",
|
||||
description: "integrity check failed",
|
||||
},
|
||||
TPMRCTicket: {
|
||||
name: "TPM_RC_TICKET",
|
||||
description: "invalid ticket",
|
||||
},
|
||||
TPMRCReservedBits: {
|
||||
name: "TPM_RC_RESERVED_BITS",
|
||||
description: "reserved bits not set to zero as required",
|
||||
},
|
||||
TPMRCBadAuth: {
|
||||
name: "TPM_RC_BAD_AUTH",
|
||||
description: "authorization failure without DA implications",
|
||||
},
|
||||
TPMRCExpired: {
|
||||
name: "TPM_RC_EXPIRED",
|
||||
description: "the policy has expired",
|
||||
},
|
||||
TPMRCPolicyCC: {
|
||||
name: "TPM_RC_POLICY_CC",
|
||||
description: "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",
|
||||
},
|
||||
TPMRCBinding: {
|
||||
name: "TPM_RC_BINDING",
|
||||
description: "public and sensitive portions of an object are not cryptographically bound",
|
||||
},
|
||||
TPMRCCurve: {
|
||||
name: "TPM_RC_CURVE",
|
||||
description: "curve not supported",
|
||||
},
|
||||
TPMRCECCPoint: {
|
||||
name: "TPM_RC_ECC_POINT",
|
||||
description: "point is not on the required curve.",
|
||||
},
|
||||
}
|
||||
|
||||
var warnDescs = map[TPMRC]errorDesc{
|
||||
TPMRCContextGap: {
|
||||
name: "TPM_RC_CONTEXT_GAP",
|
||||
description: "gap for context ID is too large",
|
||||
},
|
||||
TPMRCObjectMemory: {
|
||||
name: "TPM_RC_OBJECT_MEMORY",
|
||||
description: "out of memory for object contexts",
|
||||
},
|
||||
TPMRCSessionMemory: {
|
||||
name: "TPM_RC_SESSION_MEMORY",
|
||||
description: "out of memory for session contexts",
|
||||
},
|
||||
TPMRCMemory: {
|
||||
name: "TPM_RC_MEMORY",
|
||||
description: "out of shared object/session memory or need space for internal operations",
|
||||
},
|
||||
TPMRCSessionHandles: {
|
||||
name: "TPM_RC_SESSION_HANDLES",
|
||||
description: "out of session handles – a session must be flushed before a new session may be created",
|
||||
},
|
||||
TPMRCObjectHandles: {
|
||||
name: "TPM_RC_OBJECT_HANDLES",
|
||||
description: "out of object handles – the handle space for objects is depleted and a reboot is required",
|
||||
},
|
||||
TPMRCLocality: {
|
||||
name: "TPM_RC_LOCALITY",
|
||||
description: "bad locality",
|
||||
},
|
||||
TPMRCYielded: {
|
||||
name: "TPM_RC_YIELDED",
|
||||
description: "the TPM has suspended operation on the command; forward progress was made and the command may be retried",
|
||||
},
|
||||
TPMRCCanceled: {
|
||||
name: "TPM_RC_CANCELED",
|
||||
description: "the command was canceled",
|
||||
},
|
||||
TPMRCTesting: {
|
||||
name: "TPM_RC_TESTING",
|
||||
description: "TPM is performing self-tests",
|
||||
},
|
||||
TPMRCReferenceH0: {
|
||||
name: "TPM_RC_REFERENCE_H0",
|
||||
description: "the 1st handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceH1: {
|
||||
name: "TPM_RC_REFERENCE_H1",
|
||||
description: "the 2nd handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceH2: {
|
||||
name: "TPM_RC_REFERENCE_H2",
|
||||
description: "the 3rd handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceH3: {
|
||||
name: "TPM_RC_REFERENCE_H3",
|
||||
description: "the 4th handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceH4: {
|
||||
name: "TPM_RC_REFERENCE_H4",
|
||||
description: "the 5th handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceH5: {
|
||||
name: "TPM_RC_REFERENCE_H5",
|
||||
description: "the 6th handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceH6: {
|
||||
name: "TPM_RC_REFERENCE_H6",
|
||||
description: "the 7th handle in the handle area references a transient object or session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS0: {
|
||||
name: "TPM_RC_REFERENCE_S0",
|
||||
description: "the 1st authorization session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS1: {
|
||||
name: "TPM_RC_REFERENCE_S1",
|
||||
description: "the 2nd authorization session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS2: {
|
||||
name: "TPM_RC_REFERENCE_S2",
|
||||
description: "the 3rd authorization session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS3: {
|
||||
name: "TPM_RC_REFERENCE_S3",
|
||||
description: "the 4th authorization session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS4: {
|
||||
name: "TPM_RC_REFERENCE_S4",
|
||||
description: "the 5th session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS5: {
|
||||
name: "TPM_RC_REFERENCE_S5",
|
||||
description: "the 6th session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCReferenceS6: {
|
||||
name: "TPM_RC_REFERENCE_S6",
|
||||
description: "the 7th authorization session handle references a session that is not loaded",
|
||||
},
|
||||
TPMRCNVRate: {
|
||||
name: "TPM_RC_NV_RATE",
|
||||
description: "the TPM is rate-limiting accesses to prevent wearout of NV",
|
||||
},
|
||||
TPMRCLockout: {
|
||||
name: "TPM_RC_LOCKOUT",
|
||||
description: "authorizations for objects subject to DA protection are not allowed at this time because the TPM is in DA lockout mode",
|
||||
},
|
||||
TPMRCRetry: {
|
||||
name: "TPM_RC_RETRY",
|
||||
description: "the TPM was not able to start the command",
|
||||
},
|
||||
TPMRCNVUnavailable: {
|
||||
name: "TPM_RC_NV_UNAVAILABLE",
|
||||
description: "the command may require writing of NV and NV is not current accessible",
|
||||
},
|
||||
}
|
||||
|
||||
// subject represents a subject of a TPM error code with additional details
|
||||
// (i.e., FMT1 codes)
|
||||
type subject int
|
||||
|
||||
const (
|
||||
handleRelated subject = iota + 1
|
||||
parameterRelated
|
||||
sessionRelated
|
||||
)
|
||||
|
||||
// String returns the string representation of the ErrorSubject.
|
||||
func (s subject) String() string {
|
||||
switch s {
|
||||
case handleRelated:
|
||||
return "handle"
|
||||
case parameterRelated:
|
||||
return "parameter"
|
||||
case sessionRelated:
|
||||
return "session"
|
||||
default:
|
||||
return "unknown subject"
|
||||
}
|
||||
}
|
||||
|
||||
// TPMFmt1Error represents a TPM 2.0 format-1 error, with additional information.
|
||||
type TPMFmt1Error struct {
|
||||
// The canonical TPM error code, with handle/parameter/session info
|
||||
// stripped out.
|
||||
canonical TPMRC
|
||||
// Whether this was a handle, parameter, or session error.
|
||||
subject subject
|
||||
// Which handle, parameter, or session was in error
|
||||
index int
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
func (e TPMFmt1Error) Error() string {
|
||||
desc, ok := fmt1Descs[e.canonical]
|
||||
if !ok {
|
||||
return fmt.Sprintf("unknown format-1 error: %s %d (%x)", e.subject, e.index, uint32(e.canonical))
|
||||
}
|
||||
return fmt.Sprintf("%s (%v %d): %s", desc.name, e.subject, e.index, desc.description)
|
||||
}
|
||||
|
||||
// Handle returns whether the error is handle-related and if so, which handle is
|
||||
// in error.
|
||||
func (e TPMFmt1Error) Handle() (bool, int) {
|
||||
if e.subject != handleRelated {
|
||||
return false, 0
|
||||
}
|
||||
return true, e.index
|
||||
}
|
||||
|
||||
// Parameter returns whether the error is handle-related and if so, which handle
|
||||
// is in error.
|
||||
func (e TPMFmt1Error) Parameter() (bool, int) {
|
||||
if e.subject != parameterRelated {
|
||||
return false, 0
|
||||
}
|
||||
return true, e.index
|
||||
}
|
||||
|
||||
// Session returns whether the error is handle-related and if so, which handle
|
||||
// is in error.
|
||||
func (e TPMFmt1Error) Session() (bool, int) {
|
||||
if e.subject != sessionRelated {
|
||||
return false, 0
|
||||
}
|
||||
return true, e.index
|
||||
}
|
||||
|
||||
// isFmt0Error returns true if the result is a format-0 error.
|
||||
func (r TPMRC) isFmt0Error() bool {
|
||||
return (r&rcVer1) == rcVer1 && (r&rcWarn) != rcWarn
|
||||
}
|
||||
|
||||
// isFmt1Error returns true and a format-1 error structure if the error is a
|
||||
// format-1 error.
|
||||
func (r TPMRC) isFmt1Error() (bool, TPMFmt1Error) {
|
||||
if (r & rcFmt1) != rcFmt1 {
|
||||
return false, TPMFmt1Error{}
|
||||
}
|
||||
subj := handleRelated
|
||||
if (r & rcP) == rcP {
|
||||
subj = parameterRelated
|
||||
r ^= rcP
|
||||
} else if (r & rcS) == rcS {
|
||||
subj = sessionRelated
|
||||
r ^= rcS
|
||||
}
|
||||
idx := int((r & 0xF00) >> 8)
|
||||
r &= 0xFFFFF0FF
|
||||
return true, TPMFmt1Error{
|
||||
canonical: r,
|
||||
subject: subj,
|
||||
index: idx,
|
||||
}
|
||||
}
|
||||
|
||||
// IsWarning returns true if the error is a warning code.
|
||||
// This usually indicates a problem with the TPM state, and not the command.
|
||||
// Retrying the command later may succeed.
|
||||
func (r TPMRC) IsWarning() bool {
|
||||
if isFmt1, _ := r.isFmt1Error(); isFmt1 {
|
||||
// There aren't any format-1 warnings.
|
||||
return false
|
||||
}
|
||||
return (r&rcVer1) == rcVer1 && (r&rcWarn) == rcWarn
|
||||
}
|
||||
|
||||
// Error produces a nice human-readable representation of the error, parsing TPM
|
||||
// FMT1 errors as needed.
|
||||
func (r TPMRC) Error() string {
|
||||
if isFmt1, fmt1 := r.isFmt1Error(); isFmt1 {
|
||||
return fmt1.Error()
|
||||
}
|
||||
if r.isFmt0Error() {
|
||||
desc, ok := fmt0Descs[r]
|
||||
if !ok {
|
||||
return fmt.Sprintf("unknown format-0 error code (0x%x)", uint32(r))
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", desc.name, desc.description)
|
||||
}
|
||||
if r.IsWarning() {
|
||||
desc, ok := warnDescs[r]
|
||||
if !ok {
|
||||
return fmt.Sprintf("unknown warning (0x%x)", uint32(r))
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", desc.name, desc.description)
|
||||
}
|
||||
return fmt.Sprintf("unrecognized error code (0x%x)", uint32(r))
|
||||
}
|
||||
|
||||
// Is returns whether the TPMRC (which may be a FMT1 error) is equal to the
|
||||
// given canonical error.
|
||||
func (r TPMRC) Is(target error) bool {
|
||||
targetTPMRC, ok := target.(TPMRC)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if isFmt1, fmt1 := r.isFmt1Error(); isFmt1 {
|
||||
return fmt1.canonical == targetTPMRC
|
||||
}
|
||||
return r == targetTPMRC
|
||||
}
|
||||
|
||||
// As returns whether the error can be assigned to the given interface type.
|
||||
// If supported, it updates the value pointed at by target.
|
||||
// Supports the Fmt1Error type.
|
||||
func (r TPMRC) As(target interface{}) bool {
|
||||
pFmt1, ok := target.(*TPMFmt1Error)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
isFmt1, fmt1 := r.isFmt1Error()
|
||||
if !isFmt1 {
|
||||
return false
|
||||
}
|
||||
*pFmt1 = fmt1
|
||||
return true
|
||||
}
|
||||
29
vendor/github.com/google/go-tpm/tpm2/kdf.go
generated
vendored
Normal file
29
vendor/github.com/google/go-tpm/tpm2/kdf.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
legacy "github.com/google/go-tpm/legacy/tpm2"
|
||||
)
|
||||
|
||||
// KDFa implements TPM 2.0's default key derivation function, as defined in
|
||||
// section 11.4.9.2 of the TPM revision 2 specification part 1.
|
||||
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
|
||||
// The key & label parameters must not be zero length.
|
||||
// The label parameter is a non-null-terminated string.
|
||||
// The contextU & contextV parameters are optional.
|
||||
func KDFa(h crypto.Hash, key []byte, label string, contextU, contextV []byte, bits int) []byte {
|
||||
return legacy.KDFaHash(h, key, label, contextU, contextV, bits)
|
||||
}
|
||||
|
||||
// KDFe implements TPM 2.0's ECDH key derivation function, as defined in
|
||||
// section 11.4.9.3 of the TPM revision 2 specification part 1.
|
||||
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
|
||||
// The z parameter is the x coordinate of one party's private ECC key multiplied
|
||||
// by the other party's public ECC point.
|
||||
// The use parameter is a non-null-terminated string.
|
||||
// The partyUInfo and partyVInfo are the x coordinates of the initiator's and
|
||||
// the responder's ECC points, respectively.
|
||||
func KDFe(h crypto.Hash, z []byte, use string, partyUInfo, partyVInfo []byte, bits int) []byte {
|
||||
return legacy.KDFeHash(h, z, use, partyUInfo, partyVInfo, bits)
|
||||
}
|
||||
33
vendor/github.com/google/go-tpm/tpm2/labeled_kem_convert.go
generated
vendored
Normal file
33
vendor/github.com/google/go-tpm/tpm2/labeled_kem_convert.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnsupportedType = errors.New("unsupported key type")
|
||||
)
|
||||
|
||||
// An LabeledEncapsulationKey represents a public key used in a TPM labeled-encapsulation scheme.
|
||||
type LabeledEncapsulationKey interface {
|
||||
// Encapsulate performs the labeled key encapsulation.
|
||||
Encapsulate(random io.Reader, label string) (secret []byte, ciphertext []byte, err error)
|
||||
// NameAlg fetches the Name hash algorithm of the encapsulation key.
|
||||
NameAlg() TPMAlgID
|
||||
// SymmetricParameters fetches the symmetric parameters for protection.
|
||||
SymmetricParameters() *TPMTSymDefObject
|
||||
}
|
||||
|
||||
// ImportEncapsulationKey imports the TPM-form public key as a LabeledEncapsulationkey.
|
||||
func ImportEncapsulationKey(pub *TPMTPublic) (LabeledEncapsulationKey, error) {
|
||||
switch pub.Type {
|
||||
case TPMAlgRSA:
|
||||
return importRSAEncapsulationKey(pub)
|
||||
case TPMAlgECC:
|
||||
return importECCEncapsulationKey(pub)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w %v", ErrUnsupportedType, pub.Type)
|
||||
}
|
||||
}
|
||||
107
vendor/github.com/google/go-tpm/tpm2/labeled_kem_ecc.go
generated
vendored
Normal file
107
vendor/github.com/google/go-tpm/tpm2/labeled_kem_ecc.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto/ecdh"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
// The curve is not supported.
|
||||
ErrUnsupportedCurve = errors.New("unsupported curve")
|
||||
// There was an internal error parsing the ephemeral public key during encapsulation.
|
||||
ErrBadEphemeralKey = errors.New("bad ephemeral ECC key")
|
||||
)
|
||||
|
||||
// An eccKey is an One-Pass-Diffie-Hellman-based Labeled Encapsulation key.
|
||||
type eccKey struct {
|
||||
// The actual public key.
|
||||
eccPub *ecdh.PublicKey
|
||||
// The name algorithm of the key.
|
||||
nameAlg TPMIAlgHash
|
||||
// The symmetric parameters of the key.
|
||||
symParms *TPMTSymDefObject
|
||||
}
|
||||
|
||||
// importECCEncapsulationKey imports an ECC key for use in labeled encapsulation.
|
||||
func importECCEncapsulationKey(pub *TPMTPublic) (*eccKey, error) {
|
||||
eccParms, err := pub.Parameters.ECCDetail()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eccPub, err := pub.Unique.ECC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ecdhPub, err := ECDHPub(eccParms, eccPub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &eccKey{
|
||||
eccPub: ecdhPub,
|
||||
nameAlg: pub.NameAlg,
|
||||
symParms: &eccParms.Symmetric,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getXY gets the big-endian X/Y coordinates as full-length buffers.
|
||||
func getXY(pub *ecdh.PublicKey) ([]byte, []byte, error) {
|
||||
// Check and strip the leading 0x04 byte, which indicates an uncompressed ECC point.
|
||||
rawPub := pub.Bytes()
|
||||
if len(rawPub) == 0 || rawPub[0] != 0x04 {
|
||||
return nil, nil, fmt.Errorf("%w: could not decode %x as an uncompressed point", ErrBadEphemeralKey, rawPub)
|
||||
}
|
||||
rawPub = rawPub[1:]
|
||||
return rawPub[:len(rawPub)/2], rawPub[len(rawPub)/2:], nil
|
||||
}
|
||||
|
||||
// Encapsulate implements LabeledEncapsulationKey.
|
||||
func (pub *eccKey) Encapsulate(random io.Reader, label string) (secret []byte, ciphertext []byte, err error) {
|
||||
ephemeralPriv, err := pub.eccPub.Curve().GenerateKey(random)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return pub.encapsulateDerandomized(ephemeralPriv, label)
|
||||
}
|
||||
|
||||
// encapsulateDerandomized is a derandomized internal version of Encapsulate for testing.
|
||||
func (pub *eccKey) encapsulateDerandomized(ephPrivate *ecdh.PrivateKey, label string) (secret []byte, ciphertext []byte, err error) {
|
||||
nameHash, err := pub.nameAlg.Hash()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pubX, _, err := getXY(pub.eccPub)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ephX, ephY, err := getXY(ephPrivate.PublicKey())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
z, err := ephPrivate.ECDH(pub.eccPub)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
secret = KDFe(nameHash, z, label, ephX, pubX, nameHash.Size()*8)
|
||||
ciphertext = Marshal(TPMSECCPoint{
|
||||
X: TPM2BECCParameter{
|
||||
Buffer: ephX,
|
||||
},
|
||||
Y: TPM2BECCParameter{
|
||||
Buffer: ephY,
|
||||
},
|
||||
})
|
||||
return secret, ciphertext, nil
|
||||
}
|
||||
|
||||
// NameAlg implements LabeledEncapsulationKey.
|
||||
func (pub *eccKey) NameAlg() TPMAlgID {
|
||||
return pub.nameAlg
|
||||
}
|
||||
|
||||
// SymmetricParameters implements LabeledEncapsulationkey.
|
||||
func (pub *eccKey) SymmetricParameters() *TPMTSymDefObject {
|
||||
return pub.symParms
|
||||
}
|
||||
112
vendor/github.com/google/go-tpm/tpm2/labeled_kem_rsa.go
generated
vendored
Normal file
112
vendor/github.com/google/go-tpm/tpm2/labeled_kem_rsa.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// The source of randomness used for encapsulation ran out of data.
|
||||
ErrInsufficientRandom = errors.New("random source did not provide enough data")
|
||||
)
|
||||
|
||||
// An rsaKey is an RSA-OAEP-based Labeled Encapsulation key.
|
||||
type rsaKey struct {
|
||||
// The actual public key.
|
||||
rsaPub rsa.PublicKey
|
||||
// The scheme hash algorithm to use for the OAEP-based encapsulation.
|
||||
hash crypto.Hash
|
||||
// The name algorithm of the key.
|
||||
nameAlg TPMIAlgHash
|
||||
// The symmetric parameters of the key.
|
||||
symParms *TPMTSymDefObject
|
||||
}
|
||||
|
||||
func importRSAEncapsulationKey(pub *TPMTPublic) (*rsaKey, error) {
|
||||
rsaParms, err := pub.Parameters.RSADetail()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rsaPub, err := pub.Unique.RSA()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rsa, err := RSAPub(rsaParms, rsaPub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decide what hash algorithm to use for OAEP.
|
||||
// It's the scheme hash algorithm if not null, otherwise it's the name algorithm.
|
||||
hashAlgID := pub.NameAlg
|
||||
if rsaParms.Scheme.Scheme == TPMAlgOAEP {
|
||||
oaep, err := rsaParms.Scheme.Details.OAEP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if oaep.HashAlg != TPMAlgNull {
|
||||
hashAlgID = oaep.HashAlg
|
||||
}
|
||||
}
|
||||
hashAlg, err := hashAlgID.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &rsaKey{
|
||||
rsaPub: *rsa,
|
||||
hash: hashAlg,
|
||||
nameAlg: pub.NameAlg,
|
||||
symParms: &rsaParms.Symmetric,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encapsulate performs the OAEP-based RSA Labeled Encapsulation.
|
||||
func (pub *rsaKey) Encapsulate(random io.Reader, label string) (secret []byte, ciphertext []byte, err error) {
|
||||
secret = make([]byte, pub.hash.Size())
|
||||
n, err := random.Read(secret)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if n != len(secret) {
|
||||
return nil, nil, fmt.Errorf("%w: only read %d bytes but %d were needed", ErrInsufficientRandom, n, len(secret))
|
||||
}
|
||||
|
||||
ciphertext, err = pub.encapsulateDerandomized(random, secret, label)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return secret, ciphertext, err
|
||||
}
|
||||
|
||||
// encapsulateDerandomized is a derandomized internal version of Encapsulate for testing.
|
||||
func (pub *rsaKey) encapsulateDerandomized(oaepSaltReader io.Reader, secret []byte, label string) (ciphertext []byte, err error) {
|
||||
// Ensure label is null-terminated.
|
||||
if !strings.HasSuffix(label, "\x00") {
|
||||
label = label + "\x00"
|
||||
}
|
||||
|
||||
if len(secret) != pub.hash.Size() {
|
||||
return nil, fmt.Errorf("%w: secret was only %d bytes but %d were needed", ErrInsufficientRandom, len(secret), pub.hash.Size())
|
||||
}
|
||||
|
||||
ciphertext, err = rsa.EncryptOAEP(pub.hash.New(), oaepSaltReader, &pub.rsaPub, secret, []byte(label))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ciphertext, err
|
||||
}
|
||||
|
||||
// NameAlg implements LabeledEncapsulationKey.
|
||||
func (pub *rsaKey) NameAlg() TPMAlgID {
|
||||
return pub.nameAlg
|
||||
}
|
||||
|
||||
// SymmetricParameters implements LabeledEncapsulationkey.
|
||||
func (pub *rsaKey) SymmetricParameters() *TPMTSymDefObject {
|
||||
return pub.symParms
|
||||
}
|
||||
377
vendor/github.com/google/go-tpm/tpm2/marshalling.go
generated
vendored
Normal file
377
vendor/github.com/google/go-tpm/tpm2/marshalling.go
generated
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Marshallable represents any TPM type that can be marshalled.
|
||||
type Marshallable interface {
|
||||
// marshal will serialize the given value, appending onto the given buffer.
|
||||
// Returns an error if the value is not marshallable.
|
||||
marshal(buf *bytes.Buffer)
|
||||
}
|
||||
|
||||
// marshallableWithHint represents any TPM type that can be marshalled,
|
||||
// but that requires a selector ("hint") value when marshalling. Most TPMU_ are
|
||||
// an example of this.
|
||||
type marshallableWithHint interface {
|
||||
// get will return the corresponding union member by copy. If the union is
|
||||
// uninitialized, it will initialize a new zero-valued one.
|
||||
get(hint int64) (reflect.Value, error)
|
||||
}
|
||||
|
||||
// Unmarshallable represents any TPM type that can be marshalled or unmarshalled.
|
||||
type Unmarshallable interface {
|
||||
Marshallable
|
||||
// marshal will deserialize the given value from the given buffer.
|
||||
// Returns an error if there was an unmarshalling error or if there was not
|
||||
// enough data in the buffer.
|
||||
unmarshal(buf *bytes.Buffer) error
|
||||
}
|
||||
|
||||
// unmarshallableWithHint represents any TPM type that can be marshalled or unmarshalled,
|
||||
// but that requires a selector ("hint") value when unmarshalling. Most TPMU_ are
|
||||
// an example of this.
|
||||
type unmarshallableWithHint interface {
|
||||
marshallableWithHint
|
||||
// create will instantiate and return the corresponding union member.
|
||||
create(hint int64) (reflect.Value, error)
|
||||
}
|
||||
|
||||
// Marshal will serialize the given values, returning them as a byte slice.
|
||||
func Marshal(v Marshallable) []byte {
|
||||
var buf bytes.Buffer
|
||||
if err := marshal(&buf, reflect.ValueOf(v)); err != nil {
|
||||
panic(fmt.Sprintf("unexpected error marshalling %v: %v", reflect.TypeOf(v).Name(), err))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals the given type from the byte array.
|
||||
// Returns an error if the buffer does not contain enough data to satisfy the
|
||||
// types, or if the types are not unmarshallable.
|
||||
func Unmarshal[T Marshallable, P interface {
|
||||
*T
|
||||
Unmarshallable
|
||||
}](data []byte) (*T, error) {
|
||||
buf := bytes.NewBuffer(data)
|
||||
var t T
|
||||
value := reflect.New(reflect.TypeOf(t))
|
||||
if err := unmarshal(buf, value.Elem()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return value.Interface().(*T), nil
|
||||
}
|
||||
|
||||
// marshallableByReflection is a placeholder interface, to hint to the unmarshalling
|
||||
// library that it is supposed to use reflection.
|
||||
type marshallableByReflection interface {
|
||||
reflectionSafe()
|
||||
}
|
||||
|
||||
// marshalByReflection is embedded into any type that can be marshalled by reflection,
|
||||
// needing no custom logic.
|
||||
type marshalByReflection struct{}
|
||||
|
||||
func (marshalByReflection) reflectionSafe() {}
|
||||
|
||||
// These placeholders are required because a type constraint cannot union another interface
|
||||
// that contains methods.
|
||||
// Otherwise, marshalByReflection would not implement Unmarshallable, and the Marshal/Unmarshal
|
||||
// functions would accept interface{ Marshallable | marshallableByReflection } instead.
|
||||
|
||||
// Placeholder: because this type implements the defaultMarshallable interface,
|
||||
// the reflection library knows not to call this.
|
||||
func (marshalByReflection) marshal(_ *bytes.Buffer) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// Placeholder: because this type implements the defaultMarshallable interface,
|
||||
// the reflection library knows not to call this.
|
||||
func (*marshalByReflection) unmarshal(_ *bytes.Buffer) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// boxed is a helper type for corner cases such as unions, where all members must be structs.
|
||||
type boxed[T any] struct {
|
||||
Contents *T
|
||||
}
|
||||
|
||||
// box will put a value into a box.
|
||||
func box[T any](contents *T) boxed[T] {
|
||||
return boxed[T]{
|
||||
Contents: contents,
|
||||
}
|
||||
}
|
||||
|
||||
// unbox will take a value out of a box.
|
||||
func (b *boxed[T]) unbox() *T {
|
||||
return b.Contents
|
||||
}
|
||||
|
||||
// marshal implements the Marshallable interface.
|
||||
func (b *boxed[T]) marshal(buf *bytes.Buffer) {
|
||||
if b.Contents == nil {
|
||||
var contents T
|
||||
marshal(buf, reflect.ValueOf(&contents))
|
||||
} else {
|
||||
marshal(buf, reflect.ValueOf(b.Contents))
|
||||
}
|
||||
}
|
||||
|
||||
// unmarshal implements the Unmarshallable interface.
|
||||
func (b *boxed[T]) unmarshal(buf *bytes.Buffer) error {
|
||||
b.Contents = new(T)
|
||||
return unmarshal(buf, reflect.ValueOf(b.Contents))
|
||||
}
|
||||
|
||||
// MarshalCommand marshals a TPM command into its raw cpHash preimage format.
|
||||
// The returned bytes can be directly hashed to compute cpHash.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// cmdData, _ := MarshalCommand(myCmd)
|
||||
// cpHash := sha256.Sum256(cmdData)
|
||||
//
|
||||
// Note: Encrypted command parameters (via sessions) are not currently supported.
|
||||
// The marshaled parameters are in their unencrypted form.
|
||||
func MarshalCommand[C Command[R, *R], R any](cmd C) ([]byte, error) {
|
||||
cc := cmd.Command()
|
||||
|
||||
names, err := cmdNames(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params, err := cmdParameters(cmd, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build raw cpHash preimage: CommandCode {∥ Name1 {∥ Name2 {∥ Name3 }}} {∥ Parameters }
|
||||
// See section 16.7 of TPM 2.0 specification, part 1.
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
if err := binary.Write(buf, binary.BigEndian, cc); err != nil {
|
||||
return nil, fmt.Errorf("marshalling command code: %w", err)
|
||||
}
|
||||
|
||||
for i, name := range names {
|
||||
if _, err := buf.Write(name.Buffer); err != nil {
|
||||
return nil, fmt.Errorf("marshalling name %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := buf.Write(params); err != nil {
|
||||
return nil, fmt.Errorf("marshalling parameters: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalCommand unmarshals a raw cpHash preimage back into a TPM command.
|
||||
// The data should be the output from [MarshalCommand].
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// cmdData, _ := MarshalCommand(myCmd)
|
||||
// cmd, _ := UnmarshalCommand[MyCommandType](cmdData)
|
||||
//
|
||||
// Notes:
|
||||
// - command produced from this function is not meant to be executed directly on a TPM,
|
||||
// instead it is expected to be used for purposes such as auditing or inspection.
|
||||
// - encrypted command parameters (via sessions) are not currently supported.
|
||||
func UnmarshalCommand[C Command[R, *R], R any](data []byte) (C, error) {
|
||||
var cmd C
|
||||
|
||||
if data == nil {
|
||||
return cmd, fmt.Errorf("data cannot be nil")
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
|
||||
var cc TPMCC
|
||||
if err := binary.Read(buf, binary.BigEndian, &cc); err != nil {
|
||||
return cmd, fmt.Errorf("unmarshalling command code: %w", err)
|
||||
}
|
||||
|
||||
if cc != cmd.Command() {
|
||||
return cmd, fmt.Errorf("command code mismatch: expected %v, got %v", cmd.Command(), cc)
|
||||
}
|
||||
|
||||
expectedNames, err := cmdNames(cmd)
|
||||
if err != nil {
|
||||
return cmd, fmt.Errorf("getting expected names count: %w", err)
|
||||
}
|
||||
numNames := len(expectedNames)
|
||||
|
||||
names := make([]TPM2BName, numNames)
|
||||
for i := range numNames {
|
||||
remaining := buf.Bytes()
|
||||
if len(remaining) == 0 {
|
||||
return cmd, fmt.Errorf("unexpected end of data while parsing name %d", i)
|
||||
}
|
||||
|
||||
nameSize, err := parseNameSize(remaining)
|
||||
if err != nil {
|
||||
return cmd, fmt.Errorf("parsing name %d size: %w", i, err)
|
||||
}
|
||||
|
||||
if len(remaining) < nameSize {
|
||||
return cmd, fmt.Errorf("insufficient data for name %d: need %d bytes, have %d", i, nameSize, len(remaining))
|
||||
}
|
||||
|
||||
nameBytes := make([]byte, nameSize)
|
||||
if _, err := buf.Read(nameBytes); err != nil {
|
||||
return cmd, fmt.Errorf("reading name %d: %w", i, err)
|
||||
}
|
||||
|
||||
names[i] = TPM2BName{Buffer: nameBytes}
|
||||
}
|
||||
|
||||
// Populate the command's handle fields from the names
|
||||
if err := populateHandlesFromNames(&cmd, names); err != nil {
|
||||
return cmd, err
|
||||
}
|
||||
|
||||
params := buf.Bytes()
|
||||
|
||||
paramsBuf := bytes.NewBuffer(params)
|
||||
if err := unmarshalCmdParameters(paramsBuf, &cmd, nil); err != nil {
|
||||
return cmd, err
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseNameSize determines the size of a TPM2BName by inspecting its first bytes.
|
||||
// Returns the total size in bytes for the name.
|
||||
//
|
||||
// Case 1: Handle-based names (4 bytes)
|
||||
// - 0x0000... → PCR
|
||||
// - 0x02... → HMAC Session
|
||||
// - 0x03... → Policy Session
|
||||
// - 0x40... → Permanent Values
|
||||
//
|
||||
// Case 2: Hash-based names (2 + hash_size bytes) - for all other entities
|
||||
// - Format: nameAlg (2 bytes) || H_nameAlg (hash digest)
|
||||
//
|
||||
// See section 14 of TPM 2.0 specification, part 1.
|
||||
func parseNameSize(buf []byte) (int, error) {
|
||||
if len(buf) < 2 {
|
||||
return 0, fmt.Errorf("buffer too short to parse name")
|
||||
}
|
||||
|
||||
firstByte := TPMHT(buf[0])
|
||||
firstTwoBytes := binary.BigEndian.Uint16(buf[0:2])
|
||||
|
||||
// Case 1: Handle-based names (4 bytes)
|
||||
switch {
|
||||
case firstTwoBytes == 0x0000:
|
||||
// PCR handles (pattern: 0x0000XXXX)
|
||||
// Must check both bytes to distinguish from hash algorithms
|
||||
// that also start with 0x00 (e.g., TPMAlgSHA256 = 0x000B)
|
||||
return 4, nil
|
||||
case firstByte == TPMHTHMACSession: // 0x02
|
||||
return 4, nil
|
||||
case firstByte == TPMHTPolicySession: // 0x03
|
||||
return 4, nil
|
||||
case firstByte == TPMHTPermanent: // 0x40
|
||||
return 4, nil
|
||||
}
|
||||
|
||||
// Case 2: Hash-based names (nameAlg || hash)
|
||||
// firstTwoBytes is the algorithm ID (0x0001 to 0x00B3)
|
||||
algID := TPMIAlgHash(firstTwoBytes)
|
||||
hashAlg, err := algID.Hash()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("unsupported hash algorithm 0x%x in name: %w", firstTwoBytes, err)
|
||||
}
|
||||
|
||||
// 2 bytes for algID + hash size
|
||||
return 2 + hashAlg.Size(), nil
|
||||
}
|
||||
|
||||
// MarshalResponse marshals a TPM response into its raw rpHash preimage format.
|
||||
// The returned bytes can be directly hashed to compute rpHash.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// rspData, _ := MarshalResponse(myCmd, myRsp)
|
||||
// rpHash := sha256.Sum256(rspData)
|
||||
//
|
||||
// Note: Encrypted response parameters (via sessions) are not currently supported.
|
||||
func MarshalResponse[C Command[R, *R], R any](cmd C, rsp *R) ([]byte, error) {
|
||||
cc := cmd.Command()
|
||||
|
||||
params, err := marshalRspParameters(rsp, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build raw rpHash preimage: responseCode || commandCode || parameters
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Write responseCode (4 bytes, always 0 for successful responses)
|
||||
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
||||
return nil, fmt.Errorf("marshalling response code: %w", err)
|
||||
}
|
||||
|
||||
if err := binary.Write(buf, binary.BigEndian, cc); err != nil {
|
||||
return nil, fmt.Errorf("marshalling command code: %w", err)
|
||||
}
|
||||
|
||||
if _, err := buf.Write(params); err != nil {
|
||||
return nil, fmt.Errorf("marshalling parameters: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalResponse unmarshals a raw rpHash preimage back into a TPM response.
|
||||
// The data should be the output from [MarshalResponse].
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// rspData, _ := MarshalResponse(commandCode, myRsp)
|
||||
// rsp, _ := UnmarshalResponse[MyResponseType](rspData)
|
||||
//
|
||||
// Notes:
|
||||
// - the result from this function is expected to be used for purposes such as auditing or inspection.
|
||||
// - encrypted response parameters (via sessions) are not currently supported.
|
||||
func UnmarshalResponse[R any](data []byte) (*R, error) {
|
||||
var rsp R
|
||||
|
||||
if data == nil {
|
||||
return nil, fmt.Errorf("data cannot be nil")
|
||||
}
|
||||
|
||||
if len(data) < 8 {
|
||||
return nil, fmt.Errorf("data too short: need at least 8 bytes (responseCode + commandCode), got %d", len(data))
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
|
||||
var responseCode uint32
|
||||
if err := binary.Read(buf, binary.BigEndian, &responseCode); err != nil {
|
||||
return nil, fmt.Errorf("unmarshalling response code: %w", err)
|
||||
}
|
||||
|
||||
if responseCode != 0 {
|
||||
return nil, fmt.Errorf("invalid response code: expected 0, got 0x%x", responseCode)
|
||||
}
|
||||
|
||||
var cc TPMCC
|
||||
if err := binary.Read(buf, binary.BigEndian, &cc); err != nil {
|
||||
return nil, fmt.Errorf("unmarshalling command code: %w", err)
|
||||
}
|
||||
|
||||
params := buf.Bytes()
|
||||
|
||||
if err := rspParameters(params, nil, &rsp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rsp, nil
|
||||
}
|
||||
62
vendor/github.com/google/go-tpm/tpm2/names.go
generated
vendored
Normal file
62
vendor/github.com/google/go-tpm/tpm2/names.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// HandleName returns the TPM Name of a PCR, session, or permanent value
|
||||
// (e.g., hierarchy) handle.
|
||||
func HandleName(h TPMHandle) TPM2BName {
|
||||
result := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(result, uint32(h))
|
||||
return TPM2BName{
|
||||
Buffer: result,
|
||||
}
|
||||
}
|
||||
|
||||
// objectOrNVName calculates the Name of an NV index or object.
|
||||
// pub is a pointer to either a TPMTPublic or TPMSNVPublic.
|
||||
func objectOrNVName(alg TPMAlgID, pub interface{}) (*TPM2BName, error) {
|
||||
h, err := alg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a byte slice with the correct reserved size and marshal the
|
||||
// NameAlg to it.
|
||||
result := make([]byte, 2, 2+h.Size())
|
||||
binary.BigEndian.PutUint16(result, uint16(alg))
|
||||
|
||||
// Calculate the hash of the entire Public contents and append it to the
|
||||
// result.
|
||||
ha := h.New()
|
||||
var buf bytes.Buffer
|
||||
if err := marshal(&buf, reflect.ValueOf(pub)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ha.Write(buf.Bytes())
|
||||
result = ha.Sum(result)
|
||||
|
||||
return &TPM2BName{
|
||||
Buffer: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ObjectName returns the TPM Name of an object.
|
||||
func ObjectName(p *TPMTPublic) (*TPM2BName, error) {
|
||||
return objectOrNVName(p.NameAlg, p)
|
||||
}
|
||||
|
||||
// NVName returns the TPM Name of an NV index.
|
||||
func NVName(p *TPMSNVPublic) (*TPM2BName, error) {
|
||||
return objectOrNVName(p.NameAlg, p)
|
||||
}
|
||||
|
||||
// PrimaryHandleName returns the TPM Name of a primary handle.
|
||||
func PrimaryHandleName(h TPMHandle) []byte {
|
||||
result := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(result, uint32(h))
|
||||
return result
|
||||
}
|
||||
55
vendor/github.com/google/go-tpm/tpm2/pcrs.go
generated
vendored
Normal file
55
vendor/github.com/google/go-tpm/tpm2/pcrs.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package tpm2
|
||||
|
||||
// pcrSelectionFormatter is a Platform TPM Profile-specific interface for
|
||||
// formatting TPM PCR selections.
|
||||
// This interface isn't (yet) part of the go-tpm public interface. After we
|
||||
// add a second implementation, we should consider making it public.
|
||||
type pcrSelectionFormatter interface {
|
||||
// PCRs returns the TPM PCR selection bitmask associated with the given PCR indices.
|
||||
PCRs(pcrs ...uint) []byte
|
||||
}
|
||||
|
||||
// PCClientCompatible is a pcrSelectionFormatter that formats PCR selections
|
||||
// suitable for use in PC Client PTP-compatible TPMs (the vast majority):
|
||||
// https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
|
||||
// PC Client mandates at least 24 PCRs but does not provide an upper limit.
|
||||
var PCClientCompatible pcrSelectionFormatter = pcClient{}
|
||||
|
||||
type pcClient struct{}
|
||||
|
||||
// The TPM requires all PCR selections to be at least big enough to select all
|
||||
// the PCRs in the minimum PCR allocation.
|
||||
const pcClientMinimumPCRCount = 24
|
||||
|
||||
func (pcClient) PCRs(pcrs ...uint) []byte {
|
||||
// Find the biggest PCR we selected.
|
||||
maxPCR := uint(0)
|
||||
for _, pcr := range pcrs {
|
||||
if pcr > maxPCR {
|
||||
maxPCR = pcr
|
||||
}
|
||||
}
|
||||
selectionSize := maxPCR/8 + 1
|
||||
|
||||
// Enforce the minimum PCR selection size.
|
||||
if selectionSize < (pcClientMinimumPCRCount / 8) {
|
||||
selectionSize = (pcClientMinimumPCRCount / 8)
|
||||
}
|
||||
|
||||
// Allocate a byte array to store the bitfield, that has at least
|
||||
// enough bits to store our selections.
|
||||
selection := make([]byte, selectionSize)
|
||||
for _, pcr := range pcrs {
|
||||
// The PCR selection mask is byte-wise little-endian:
|
||||
// select[0] contains bits representing the selection of PCRs 0 through 7
|
||||
// select[1] contains PCRs 8 through 15, and so on.
|
||||
byteIdx := pcr / 8
|
||||
// Within the byte, the PCR selection is bit-wise big-endian:
|
||||
// bit 0 of select[0] contains the selection of PCR 0
|
||||
// bit 1 of select[0] contains the selection of PCR 1, and so on.
|
||||
bitIdx := pcr % 8
|
||||
|
||||
selection[byteIdx] |= (1 << bitIdx)
|
||||
}
|
||||
return selection
|
||||
}
|
||||
60
vendor/github.com/google/go-tpm/tpm2/policy.go
generated
vendored
Normal file
60
vendor/github.com/google/go-tpm/tpm2/policy.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// PolicyCalculator represents a TPM 2.0 policy that needs to be calculated
|
||||
// synthetically (i.e., without a TPM).
|
||||
type PolicyCalculator struct {
|
||||
alg TPMIAlgHash
|
||||
hash crypto.Hash
|
||||
state []byte
|
||||
}
|
||||
|
||||
// NewPolicyCalculator creates a fresh policy using the given hash algorithm.
|
||||
func NewPolicyCalculator(alg TPMIAlgHash) (*PolicyCalculator, error) {
|
||||
hash, err := alg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PolicyCalculator{
|
||||
alg: alg,
|
||||
hash: hash,
|
||||
state: make([]byte, hash.Size()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Reset resets the internal state of the policy hash to all 0x00.
|
||||
func (p *PolicyCalculator) Reset() {
|
||||
p.state = make([]byte, p.hash.Size())
|
||||
}
|
||||
|
||||
// Update updates the internal state of the policy hash by appending the
|
||||
// current state with the given contents, and updating the new state to the
|
||||
// hash of that.
|
||||
func (p *PolicyCalculator) Update(data ...interface{}) error {
|
||||
hash := p.hash.New()
|
||||
hash.Write(p.state)
|
||||
var buf bytes.Buffer
|
||||
for _, d := range data {
|
||||
if err := marshal(&buf, reflect.ValueOf(d)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
hash.Write(buf.Bytes())
|
||||
p.state = hash.Sum(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash returns the current state of the policy hash.
|
||||
func (p *PolicyCalculator) Hash() *TPMTHA {
|
||||
result := TPMTHA{
|
||||
HashAlg: p.alg,
|
||||
Digest: make([]byte, len(p.state)),
|
||||
}
|
||||
copy(result.Digest, p.state)
|
||||
return &result
|
||||
}
|
||||
1300
vendor/github.com/google/go-tpm/tpm2/reflect.go
generated
vendored
Normal file
1300
vendor/github.com/google/go-tpm/tpm2/reflect.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
996
vendor/github.com/google/go-tpm/tpm2/sessions.go
generated
vendored
Normal file
996
vendor/github.com/google/go-tpm/tpm2/sessions.go
generated
vendored
Normal file
@@ -0,0 +1,996 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-tpm/tpm2/transport"
|
||||
)
|
||||
|
||||
// Session represents a session in the TPM.
|
||||
type Session interface {
|
||||
// Initializes the session, if needed. Has no effect if not needed or
|
||||
// already done. Some types of sessions may need to be initialized
|
||||
// just-in-time, e.g., to support calling patterns that help the user
|
||||
// securely authorize their actions without writing a lot of code.
|
||||
Init(tpm transport.TPM) error
|
||||
// Cleans up the session, if needed.
|
||||
// Some types of session need to be cleaned up if the command failed,
|
||||
// again to support calling patterns that help the user securely
|
||||
// authorize their actions without writing a lot of code.
|
||||
CleanupFailure(tpm transport.TPM) error
|
||||
// The last nonceTPM for this session.
|
||||
NonceTPM() TPM2BNonce
|
||||
// Updates nonceCaller to a new random value.
|
||||
NewNonceCaller() error
|
||||
// Computes the authorization HMAC for the session.
|
||||
// If this is the first authorization session for a command, and
|
||||
// there is another session (or sessions) for parameter
|
||||
// decryption and/or encryption, then addNonces contains the
|
||||
// nonceTPMs from each of them, respectively (see Part 1, 19.6.5)
|
||||
Authorize(cc TPMCC, parms, addNonces []byte, names []TPM2BName, authIndex int) (*TPMSAuthCommand, error)
|
||||
// Validates the response for the session.
|
||||
// Updates NonceTPM for the session.
|
||||
Validate(rc TPMRC, cc TPMCC, parms []byte, names []TPM2BName, authIndex int, auth *TPMSAuthResponse) error
|
||||
// Returns true if this is an encryption session.
|
||||
IsEncryption() bool
|
||||
// Returns true if this is a decryption session.
|
||||
IsDecryption() bool
|
||||
// If this session is used for parameter decryption, encrypts the
|
||||
// parameter. Otherwise, does not modify the parameter.
|
||||
Encrypt(parameter []byte) error
|
||||
// If this session is used for parameter encryption, encrypts the
|
||||
// parameter. Otherwise, does not modify the parameter.
|
||||
Decrypt(parameter []byte) error
|
||||
// Returns the handle value of this session.
|
||||
Handle() TPMHandle
|
||||
}
|
||||
|
||||
// CPHash calculates the TPM command parameter hash for a given Command.
|
||||
// N.B. Authorization sessions on handles are ignored, but names aren't.
|
||||
func CPHash[R any](alg TPMIAlgHash, cmd Command[R, *R]) (*TPM2BDigest, error) {
|
||||
cc := cmd.Command()
|
||||
names, err := cmdNames(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parms, err := cmdParameters(cmd, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digest, err := cpHash(alg, cc, names, parms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &TPM2BDigest{
|
||||
Buffer: digest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// pwSession represents a password-pseudo-session.
|
||||
type pwSession struct {
|
||||
auth []byte
|
||||
}
|
||||
|
||||
// PasswordAuth assembles a password pseudo-session with the given auth value.
|
||||
func PasswordAuth(auth []byte) Session {
|
||||
return &pwSession{
|
||||
auth: auth,
|
||||
}
|
||||
}
|
||||
|
||||
// Init is not required and has no effect for a password session.
|
||||
func (s *pwSession) Init(_ transport.TPM) error { return nil }
|
||||
|
||||
// Cleanup is not required and has no effect for a password session.
|
||||
func (s *pwSession) CleanupFailure(_ transport.TPM) error { return nil }
|
||||
|
||||
// NonceTPM normally returns the last nonceTPM value from the session.
|
||||
// Since a password session is a pseudo-session with the auth value stuffed
|
||||
// in where the HMAC should go, this is not used.
|
||||
func (s *pwSession) NonceTPM() TPM2BNonce { return TPM2BNonce{} }
|
||||
|
||||
// NewNonceCaller updates the nonceCaller for this session.
|
||||
// Password sessions don't have nonces.
|
||||
func (s *pwSession) NewNonceCaller() error { return nil }
|
||||
|
||||
// Computes the authorization structure for the session.
|
||||
func (s *pwSession) Authorize(_ TPMCC, _, _ []byte, _ []TPM2BName, _ int) (*TPMSAuthCommand, error) {
|
||||
return &TPMSAuthCommand{
|
||||
Handle: TPMRSPW,
|
||||
Nonce: TPM2BNonce{},
|
||||
Attributes: TPMASession{},
|
||||
Authorization: TPM2BData{
|
||||
Buffer: s.auth,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Validates the response session structure for the session.
|
||||
func (s *pwSession) Validate(_ TPMRC, _ TPMCC, _ []byte, _ []TPM2BName, _ int, auth *TPMSAuthResponse) error {
|
||||
if len(auth.Nonce.Buffer) != 0 {
|
||||
return fmt.Errorf("expected empty nonce in response auth to PW session, got %x", auth.Nonce)
|
||||
}
|
||||
expectedAttrs := TPMASession{
|
||||
ContinueSession: true,
|
||||
}
|
||||
if auth.Attributes != expectedAttrs {
|
||||
return fmt.Errorf("expected only ContinueSession in response auth to PW session, got %v", auth.Attributes)
|
||||
}
|
||||
if len(auth.Authorization.Buffer) != 0 {
|
||||
return fmt.Errorf("expected empty HMAC in response auth to PW session, got %x", auth.Authorization)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEncryption returns true if this is an encryption session.
|
||||
// Password sessions can't be used for encryption.
|
||||
func (s *pwSession) IsEncryption() bool { return false }
|
||||
|
||||
// IsDecryption returns true if this is a decryption session.
|
||||
// Password sessions can't be used for decryption.
|
||||
func (s *pwSession) IsDecryption() bool { return false }
|
||||
|
||||
// If this session is used for parameter decryption, encrypts the
|
||||
// parameter. Otherwise, does not modify the parameter.
|
||||
// Password sessions can't be used for decryption.
|
||||
func (s *pwSession) Encrypt(_ []byte) error { return nil }
|
||||
|
||||
// If this session is used for parameter encryption, encrypts the
|
||||
// parameter. Otherwise, does not modify the parameter.
|
||||
// Password sessions can't be used for encryption.
|
||||
func (s *pwSession) Decrypt(_ []byte) error { return nil }
|
||||
|
||||
// Handle returns the handle value associated with this session.
|
||||
// In the case of a password session, this is always TPM_RS_PW.
|
||||
func (s *pwSession) Handle() TPMHandle { return TPMRSPW }
|
||||
|
||||
// cpHash calculates the TPM command parameter hash.
|
||||
// cpHash = hash(CC || names || parms)
|
||||
func cpHash(alg TPMIAlgHash, cc TPMCC, names []TPM2BName, parms []byte) ([]byte, error) {
|
||||
ha, err := alg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h := ha.New()
|
||||
binary.Write(h, binary.BigEndian, cc)
|
||||
for _, name := range names {
|
||||
h.Write(name.Buffer)
|
||||
}
|
||||
h.Write(parms)
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
// rpHash calculates the TPM response parameter hash.
|
||||
// rpHash = hash(RC || CC || parms)
|
||||
func rpHash(alg TPMIAlgHash, rc TPMRC, cc TPMCC, parms []byte) ([]byte, error) {
|
||||
ha, err := alg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h := ha.New()
|
||||
binary.Write(h, binary.BigEndian, rc)
|
||||
binary.Write(h, binary.BigEndian, cc)
|
||||
h.Write(parms)
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
// sessionOptions represents extra options used when setting up an HMAC or policy session.
|
||||
type sessionOptions struct {
|
||||
auth []byte
|
||||
password bool
|
||||
bindHandle TPMIDHEntity
|
||||
bindName TPM2BName
|
||||
bindAuth []byte
|
||||
saltHandle TPMIDHObject
|
||||
saltPub TPMTPublic
|
||||
attrs TPMASession
|
||||
symmetric TPMTSymDef
|
||||
trialPolicy bool
|
||||
}
|
||||
|
||||
// defaultOptions represents the default options used when none are provided.
|
||||
func defaultOptions() sessionOptions {
|
||||
return sessionOptions{
|
||||
symmetric: TPMTSymDef{
|
||||
Algorithm: TPMAlgNull,
|
||||
},
|
||||
bindHandle: TPMRHNull,
|
||||
saltHandle: TPMRHNull,
|
||||
}
|
||||
}
|
||||
|
||||
// AuthOption is an option for setting up an auth session variadically.
|
||||
type AuthOption func(*sessionOptions)
|
||||
|
||||
// Auth uses the session to prove knowledge of the object's auth value.
|
||||
func Auth(auth []byte) AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.auth = auth
|
||||
}
|
||||
}
|
||||
|
||||
// Password is a policy-session-only option that specifies to provide the
|
||||
// object's auth value in place of the authorization HMAC when authorizing.
|
||||
// For HMAC sessions, has the same effect as using Auth.
|
||||
// Deprecated: This is not recommended and is only provided for completeness;
|
||||
// use Auth instead.
|
||||
func Password(auth []byte) AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.auth = auth
|
||||
o.password = true
|
||||
}
|
||||
}
|
||||
|
||||
// Bound specifies that this session's session key should depend on the auth
|
||||
// value of the given object.
|
||||
func Bound(handle TPMIDHEntity, name TPM2BName, auth []byte) AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.bindHandle = handle
|
||||
o.bindName = name
|
||||
o.bindAuth = auth
|
||||
}
|
||||
}
|
||||
|
||||
// Salted specifies that this session's session key should depend on an
|
||||
// encrypted seed value using the given public key.
|
||||
// 'handle' must refer to a loaded RSA or ECC key.
|
||||
func Salted(handle TPMIDHObject, pub TPMTPublic) AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.saltHandle = handle
|
||||
o.saltPub = pub
|
||||
}
|
||||
}
|
||||
|
||||
// parameterEncryptiontpm2ion specifies whether the session-encrypted
|
||||
// parameters are encrypted on the way into the TPM, out of the TPM, or both.
|
||||
type parameterEncryptiontpm2ion int
|
||||
|
||||
const (
|
||||
// EncryptIn specifies a decrypt session.
|
||||
EncryptIn parameterEncryptiontpm2ion = 1 + iota
|
||||
// EncryptOut specifies an encrypt session.
|
||||
EncryptOut
|
||||
// EncryptInOut specifies a decrypt+encrypt session.
|
||||
EncryptInOut
|
||||
)
|
||||
|
||||
// AESEncryption uses the session to encrypt the first parameter sent to/from
|
||||
// the TPM.
|
||||
// Note that only commands whose first command/response parameter is a 2B can
|
||||
// support session encryption.
|
||||
func AESEncryption(keySize TPMKeyBits, dir parameterEncryptiontpm2ion) AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.attrs.Decrypt = (dir == EncryptIn || dir == EncryptInOut)
|
||||
o.attrs.Encrypt = (dir == EncryptOut || dir == EncryptInOut)
|
||||
o.symmetric = TPMTSymDef{
|
||||
Algorithm: TPMAlgAES,
|
||||
KeyBits: NewTPMUSymKeyBits(
|
||||
TPMAlgAES,
|
||||
TPMKeyBits(keySize),
|
||||
),
|
||||
Mode: NewTPMUSymMode(
|
||||
TPMAlgAES,
|
||||
TPMAlgCFB,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Audit uses the session to compute extra HMACs.
|
||||
// An Audit session can be used with GetSessionAuditDigest to obtain attestation
|
||||
// over a sequence of commands.
|
||||
func Audit() AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.attrs.Audit = true
|
||||
}
|
||||
}
|
||||
|
||||
// AuditExclusive is like an audit session, but even more powerful.
|
||||
// This allows an audit session to additionally indicate that no other auditable
|
||||
// commands were executed other than the ones described by the audit hash.
|
||||
func AuditExclusive() AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.attrs.Audit = true
|
||||
o.attrs.AuditExclusive = true
|
||||
}
|
||||
}
|
||||
|
||||
// Trial indicates that the policy session should be in trial-mode.
|
||||
// This allows using the TPM to calculate policy hashes.
|
||||
// This option has no effect on non-Policy sessions.
|
||||
func Trial() AuthOption {
|
||||
return func(o *sessionOptions) {
|
||||
o.trialPolicy = true
|
||||
}
|
||||
}
|
||||
|
||||
// hmacSession generally implements the HMAC session.
|
||||
type hmacSession struct {
|
||||
sessionOptions
|
||||
hash TPMIAlgHash
|
||||
nonceSize int
|
||||
handle TPMHandle
|
||||
sessionKey []byte
|
||||
// last nonceCaller
|
||||
nonceCaller TPM2BNonce
|
||||
// last nonceTPM
|
||||
nonceTPM TPM2BNonce
|
||||
}
|
||||
|
||||
// HMAC sets up a just-in-time HMAC session that is used only once.
|
||||
// A real session is created, but just in time and it is flushed when used.
|
||||
func HMAC(hash TPMIAlgHash, nonceSize int, opts ...AuthOption) Session {
|
||||
// Set up a one-off session that knows the auth value.
|
||||
sess := hmacSession{
|
||||
sessionOptions: defaultOptions(),
|
||||
hash: hash,
|
||||
nonceSize: nonceSize,
|
||||
handle: TPMRHNull,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&sess.sessionOptions)
|
||||
}
|
||||
return &sess
|
||||
}
|
||||
|
||||
// HMACSession sets up a reusable HMAC session that needs to be closed.
|
||||
func HMACSession(t transport.TPM, hash TPMIAlgHash, nonceSize int, opts ...AuthOption) (s Session, close func() error, err error) {
|
||||
// Set up a not-one-off session that knows the auth value.
|
||||
sess := hmacSession{
|
||||
sessionOptions: defaultOptions(),
|
||||
hash: hash,
|
||||
nonceSize: nonceSize,
|
||||
handle: TPMRHNull,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&sess.sessionOptions)
|
||||
}
|
||||
// This session is reusable and is closed with the function we'll
|
||||
// return.
|
||||
sess.sessionOptions.attrs.ContinueSession = true
|
||||
|
||||
// Initialize the session.
|
||||
if err := sess.Init(t); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
closer := func() error {
|
||||
_, err := (&FlushContext{FlushHandle: sess.handle}).Execute(t)
|
||||
return err
|
||||
}
|
||||
|
||||
return &sess, closer, nil
|
||||
}
|
||||
|
||||
// getEncryptedSalt creates a salt value for salted sessions.
|
||||
// Returns the encrypted salt and plaintext salt, or an error value.
|
||||
func getEncryptedSalt(pub TPMTPublic) (*TPM2BEncryptedSecret, []byte, error) {
|
||||
key, err := ImportEncapsulationKey(&pub)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
salt, encSalt, err := CreateEncryptedSalt(rand.Reader, key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &TPM2BEncryptedSecret{
|
||||
Buffer: encSalt,
|
||||
}, salt, nil
|
||||
}
|
||||
|
||||
// Init initializes the session, just in time, if needed.
|
||||
func (s *hmacSession) Init(t transport.TPM) error {
|
||||
if s.handle != TPMRHNull {
|
||||
// Session is already initialized.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get a high-quality nonceCaller for our use.
|
||||
// Store it with the session object for later reference.
|
||||
s.nonceCaller = TPM2BNonce{
|
||||
Buffer: make([]byte, s.nonceSize),
|
||||
}
|
||||
if _, err := rand.Read(s.nonceCaller.Buffer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start up the actual auth session.
|
||||
sasCmd := StartAuthSession{
|
||||
TPMKey: s.saltHandle,
|
||||
Bind: s.bindHandle,
|
||||
NonceCaller: s.nonceCaller,
|
||||
SessionType: TPMSEHMAC,
|
||||
Symmetric: s.symmetric,
|
||||
AuthHash: s.hash,
|
||||
}
|
||||
var salt []byte
|
||||
if s.saltHandle != TPMRHNull {
|
||||
var err error
|
||||
var encSalt *TPM2BEncryptedSecret
|
||||
encSalt, salt, err = getEncryptedSalt(s.saltPub)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sasCmd.EncryptedSalt = *encSalt
|
||||
}
|
||||
sasRsp, err := sasCmd.Execute(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.handle = TPMHandle(sasRsp.SessionHandle.HandleValue())
|
||||
s.nonceTPM = sasRsp.NonceTPM
|
||||
// Part 1, 19.6
|
||||
ha, err := s.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s.bindHandle != TPMRHNull || len(salt) != 0 {
|
||||
var authSalt []byte
|
||||
authSalt = append(authSalt, s.bindAuth...)
|
||||
authSalt = append(authSalt, salt...)
|
||||
s.sessionKey = KDFa(ha, authSalt, "ATH", s.nonceTPM.Buffer, s.nonceCaller.Buffer, ha.Size()*8)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cleanup cleans up the session, if needed.
|
||||
func (s *hmacSession) CleanupFailure(t transport.TPM) error {
|
||||
// The user is already responsible to clean up this session.
|
||||
if s.attrs.ContinueSession {
|
||||
return nil
|
||||
}
|
||||
fc := FlushContext{FlushHandle: s.handle}
|
||||
if _, err := fc.Execute(t); err != nil {
|
||||
return err
|
||||
}
|
||||
s.handle = TPMRHNull
|
||||
return nil
|
||||
}
|
||||
|
||||
// NonceTPM returns the last nonceTPM value from the session.
|
||||
// May be nil, if the session hasn't been initialized yet.
|
||||
func (s *hmacSession) NonceTPM() TPM2BNonce { return s.nonceTPM }
|
||||
|
||||
// To avoid a circular dependency on gotpm by tpm2, implement a
|
||||
// tiny serialization by hand for TPMASession here
|
||||
func attrsToBytes(attrs TPMASession) []byte {
|
||||
var res byte
|
||||
if attrs.ContinueSession {
|
||||
res |= (1 << 0)
|
||||
}
|
||||
if attrs.AuditExclusive {
|
||||
res |= (1 << 1)
|
||||
}
|
||||
if attrs.AuditReset {
|
||||
res |= (1 << 2)
|
||||
}
|
||||
if attrs.Decrypt {
|
||||
res |= (1 << 5)
|
||||
}
|
||||
if attrs.Encrypt {
|
||||
res |= (1 << 6)
|
||||
}
|
||||
if attrs.Audit {
|
||||
res |= (1 << 7)
|
||||
}
|
||||
return []byte{res}
|
||||
}
|
||||
|
||||
// computeHMAC computes an authorization HMAC according to various equations in
|
||||
// Part 1.
|
||||
// This applies to both commands and responses.
|
||||
// The value of key depends on whether the session is bound and/or salted.
|
||||
// pHash cpHash for a command, or an rpHash for a response.
|
||||
// nonceNewer in a command is the new nonceCaller sent in the command session packet.
|
||||
// nonceNewer in a response is the new nonceTPM sent in the response session packet.
|
||||
// nonceOlder in a command is the last nonceTPM sent by the TPM for this session.
|
||||
// This may be when the session was created, or the last time it was used.
|
||||
// nonceOlder in a response is the corresponding nonceCaller sent in the command.
|
||||
func computeHMAC(alg TPMIAlgHash, key, pHash, nonceNewer, nonceOlder, addNonces []byte, attrs TPMASession) ([]byte, error) {
|
||||
ha, err := alg.Hash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mac := hmac.New(ha.New, key)
|
||||
mac.Write(pHash)
|
||||
mac.Write(nonceNewer)
|
||||
mac.Write(nonceOlder)
|
||||
mac.Write(addNonces)
|
||||
mac.Write(attrsToBytes(attrs))
|
||||
return mac.Sum(nil), nil
|
||||
}
|
||||
|
||||
// Trim trailing zeros from the auth value. Part 1, 19.6.5, Note 2
|
||||
// Does not allocate a new underlying byte array.
|
||||
func hmacKeyFromAuthValue(auth []byte) []byte {
|
||||
key := auth
|
||||
for i := len(key) - 1; i >= 0; i-- {
|
||||
if key[i] == 0 {
|
||||
key = key[:i]
|
||||
}
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// NewNonceCaller updates the nonceCaller for this session.
|
||||
func (s *hmacSession) NewNonceCaller() error {
|
||||
_, err := rand.Read(s.nonceCaller.Buffer)
|
||||
return err
|
||||
}
|
||||
|
||||
// Authorize computes the authorization structure for the session.
|
||||
// Unlike the TPM spec, authIndex is zero-based.
|
||||
func (s *hmacSession) Authorize(cc TPMCC, parms, addNonces []byte, names []TPM2BName, authIndex int) (*TPMSAuthCommand, error) {
|
||||
if s.handle == TPMRHNull {
|
||||
// Session is not initialized.
|
||||
return nil, fmt.Errorf("session not initialized")
|
||||
}
|
||||
|
||||
// Part 1, 19.6
|
||||
// HMAC key is (sessionKey || auth) unless this session is authorizing
|
||||
// its bind target
|
||||
var hmacKey []byte
|
||||
hmacKey = append(hmacKey, s.sessionKey...)
|
||||
if len(s.bindName.Buffer) == 0 || authIndex >= len(names) || !bytes.Equal(names[authIndex].Buffer, s.bindName.Buffer) {
|
||||
hmacKey = append(hmacKey, hmacKeyFromAuthValue(s.auth)...)
|
||||
}
|
||||
|
||||
// Compute the authorization HMAC.
|
||||
cph, err := cpHash(s.hash, cc, names, parms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hmac, err := computeHMAC(s.hash, hmacKey, cph, s.nonceCaller.Buffer, s.nonceTPM.Buffer, addNonces, s.attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := TPMSAuthCommand{
|
||||
Handle: s.handle,
|
||||
Nonce: s.nonceCaller,
|
||||
Attributes: s.attrs,
|
||||
Authorization: TPM2BData{
|
||||
Buffer: hmac,
|
||||
},
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// Validate validates the response session structure for the session.
|
||||
// It updates nonceTPM from the TPM's response.
|
||||
func (s *hmacSession) Validate(rc TPMRC, cc TPMCC, parms []byte, names []TPM2BName, authIndex int, auth *TPMSAuthResponse) error {
|
||||
// Track the new nonceTPM for the session.
|
||||
s.nonceTPM = auth.Nonce
|
||||
// Track the session being automatically flushed.
|
||||
if !auth.Attributes.ContinueSession {
|
||||
s.handle = TPMRHNull
|
||||
}
|
||||
|
||||
// Part 1, 19.6
|
||||
// HMAC key is (sessionKey || auth) unless this session is authorizing
|
||||
// its bind target
|
||||
var hmacKey []byte
|
||||
hmacKey = append(hmacKey, s.sessionKey...)
|
||||
if len(s.bindName.Buffer) == 0 || authIndex >= len(names) || !bytes.Equal(names[authIndex].Buffer, s.bindName.Buffer) {
|
||||
hmacKey = append(hmacKey, hmacKeyFromAuthValue(s.auth)...)
|
||||
}
|
||||
|
||||
// Compute the authorization HMAC.
|
||||
rph, err := rpHash(s.hash, rc, cc, parms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mac, err := computeHMAC(s.hash, hmacKey, rph, s.nonceTPM.Buffer, s.nonceCaller.Buffer, nil, auth.Attributes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Compare the HMAC (constant time)
|
||||
if !hmac.Equal(mac, auth.Authorization.Buffer) {
|
||||
return fmt.Errorf("incorrect authorization HMAC")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEncryption returns true if this is an encryption session.
|
||||
func (s *hmacSession) IsEncryption() bool {
|
||||
return s.attrs.Encrypt
|
||||
}
|
||||
|
||||
// IsDecryption returns true if this is a decryption session.
|
||||
func (s *hmacSession) IsDecryption() bool {
|
||||
return s.attrs.Decrypt
|
||||
}
|
||||
|
||||
// Encrypt decrypts the parameter in place, if this session is used for
|
||||
// parameter decryption. Otherwise, it does not modify the parameter.
|
||||
func (s *hmacSession) Encrypt(parameter []byte) error {
|
||||
if !s.IsDecryption() {
|
||||
return nil
|
||||
}
|
||||
// Only AES-CFB is supported.
|
||||
bits, err := s.symmetric.KeyBits.AES()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyBytes := *bits / 8
|
||||
keyIVBytes := int(keyBytes) + 16
|
||||
var sessionValue []byte
|
||||
sessionValue = append(sessionValue, s.sessionKey...)
|
||||
sessionValue = append(sessionValue, s.auth...)
|
||||
ha, err := s.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyIV := KDFa(ha, sessionValue, "CFB", s.nonceCaller.Buffer, s.nonceTPM.Buffer, keyIVBytes*8)
|
||||
key, err := aes.NewCipher(keyIV[:keyBytes])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream := cipher.NewCFBEncrypter(key, keyIV[keyBytes:])
|
||||
stream.XORKeyStream(parameter, parameter)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decrypt encrypts the parameter in place, if this session is used for
|
||||
// parameter encryption. Otherwise, it does not modify the parameter.
|
||||
func (s *hmacSession) Decrypt(parameter []byte) error {
|
||||
if !s.IsEncryption() {
|
||||
return nil
|
||||
}
|
||||
// Only AES-CFB is supported.
|
||||
bits, err := s.symmetric.KeyBits.AES()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyBytes := *bits / 8
|
||||
keyIVBytes := int(keyBytes) + 16
|
||||
// Part 1, 21.1
|
||||
var sessionValue []byte
|
||||
sessionValue = append(sessionValue, s.sessionKey...)
|
||||
sessionValue = append(sessionValue, s.auth...)
|
||||
ha, err := s.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyIV := KDFa(ha, sessionValue, "CFB", s.nonceTPM.Buffer, s.nonceCaller.Buffer, keyIVBytes*8)
|
||||
key, err := aes.NewCipher(keyIV[:keyBytes])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream := cipher.NewCFBDecrypter(key, keyIV[keyBytes:])
|
||||
stream.XORKeyStream(parameter, parameter)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle returns the handle value of the session.
|
||||
// If the session is created with HMAC (instead of HMACSession) this will be
|
||||
// TPM_RH_NULL.
|
||||
func (s *hmacSession) Handle() TPMHandle {
|
||||
return s.handle
|
||||
}
|
||||
|
||||
// PolicyCallback represents an object's policy in the form of a function.
|
||||
// This function makes zero or more TPM policy commands and returns error.
|
||||
type PolicyCallback = func(tpm transport.TPM, handle TPMISHPolicy, nonceTPM TPM2BNonce) error
|
||||
|
||||
// policySession generally implements the policy session.
|
||||
type policySession struct {
|
||||
sessionOptions
|
||||
hash TPMIAlgHash
|
||||
nonceSize int
|
||||
handle TPMHandle
|
||||
sessionKey []byte
|
||||
// last nonceCaller
|
||||
nonceCaller TPM2BNonce
|
||||
// last nonceTPM
|
||||
nonceTPM TPM2BNonce
|
||||
callback *PolicyCallback
|
||||
}
|
||||
|
||||
// Policy sets up a just-in-time policy session that created each time it's
|
||||
// needed.
|
||||
// Each time the policy is created, the callback is invoked to authorize the
|
||||
// session.
|
||||
// A real session is created, but just in time, and it is flushed when used.
|
||||
func Policy(hash TPMIAlgHash, nonceSize int, callback PolicyCallback, opts ...AuthOption) Session {
|
||||
// Set up a one-off session that knows the auth value.
|
||||
sess := policySession{
|
||||
sessionOptions: defaultOptions(),
|
||||
hash: hash,
|
||||
nonceSize: nonceSize,
|
||||
handle: TPMRHNull,
|
||||
callback: &callback,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&sess.sessionOptions)
|
||||
}
|
||||
return &sess
|
||||
}
|
||||
|
||||
// PolicySession opens a policy session that needs to be closed.
|
||||
// The caller is responsible to call whichever policy commands they want in the
|
||||
// session.
|
||||
// Note that the TPM resets a policy session after it is successfully used.
|
||||
func PolicySession(t transport.TPM, hash TPMIAlgHash, nonceSize int, opts ...AuthOption) (s Session, close func() error, err error) {
|
||||
// Set up a not-one-off session that knows the auth value.
|
||||
sess := policySession{
|
||||
sessionOptions: defaultOptions(),
|
||||
hash: hash,
|
||||
nonceSize: nonceSize,
|
||||
handle: TPMRHNull,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&sess.sessionOptions)
|
||||
}
|
||||
|
||||
// This session is reusable and is closed with the function we'll
|
||||
// return.
|
||||
sess.sessionOptions.attrs.ContinueSession = true
|
||||
|
||||
// Initialize the session.
|
||||
if err := sess.Init(t); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
closer := func() error {
|
||||
_, err := (&FlushContext{sess.handle}).Execute(t)
|
||||
return err
|
||||
}
|
||||
|
||||
return &sess, closer, nil
|
||||
}
|
||||
|
||||
// Init initializes the session, just in time, if needed.
|
||||
func (s *policySession) Init(t transport.TPM) error {
|
||||
if s.handle != TPMRHNull {
|
||||
// Session is already initialized.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get a high-quality nonceCaller for our use.
|
||||
// Store it with the session object for later reference.
|
||||
s.nonceCaller = TPM2BNonce{
|
||||
Buffer: make([]byte, s.nonceSize),
|
||||
}
|
||||
if _, err := rand.Read(s.nonceCaller.Buffer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sessType := TPMSEPolicy
|
||||
if s.sessionOptions.trialPolicy {
|
||||
sessType = TPMSETrial
|
||||
}
|
||||
|
||||
// Start up the actual auth session.
|
||||
sasCmd := StartAuthSession{
|
||||
TPMKey: s.saltHandle,
|
||||
Bind: s.bindHandle,
|
||||
NonceCaller: s.nonceCaller,
|
||||
SessionType: sessType,
|
||||
Symmetric: s.symmetric,
|
||||
AuthHash: s.hash,
|
||||
}
|
||||
var salt []byte
|
||||
if s.saltHandle != TPMRHNull {
|
||||
var err error
|
||||
var encSalt *TPM2BEncryptedSecret
|
||||
encSalt, salt, err = getEncryptedSalt(s.saltPub)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sasCmd.EncryptedSalt = *encSalt
|
||||
}
|
||||
sasRsp, err := sasCmd.Execute(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.handle = TPMHandle(sasRsp.SessionHandle.HandleValue())
|
||||
s.nonceTPM = sasRsp.NonceTPM
|
||||
// Part 1, 19.6
|
||||
if s.bindHandle != TPMRHNull || len(salt) != 0 {
|
||||
var authSalt []byte
|
||||
authSalt = append(authSalt, s.bindAuth...)
|
||||
authSalt = append(authSalt, salt...)
|
||||
ha, err := s.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.sessionKey = KDFa(ha, authSalt, "ATH", s.nonceTPM.Buffer, s.nonceCaller.Buffer, ha.Size()*8)
|
||||
}
|
||||
|
||||
// Call the callback to execute the policy, if needed
|
||||
if s.callback != nil {
|
||||
if err := (*s.callback)(t, s.handle, s.nonceTPM); err != nil {
|
||||
return fmt.Errorf("executing policy: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanupFailure cleans up the session, if needed.
|
||||
func (s *policySession) CleanupFailure(t transport.TPM) error {
|
||||
// The user is already responsible to clean up this session.
|
||||
if s.attrs.ContinueSession {
|
||||
return nil
|
||||
}
|
||||
fc := FlushContext{FlushHandle: s.handle}
|
||||
if _, err := fc.Execute(t); err != nil {
|
||||
return err
|
||||
}
|
||||
s.handle = TPMRHNull
|
||||
return nil
|
||||
}
|
||||
|
||||
// NonceTPM returns the last nonceTPM value from the session.
|
||||
// May be nil, if the session hasn't been initialized yet.
|
||||
func (s *policySession) NonceTPM() TPM2BNonce { return s.nonceTPM }
|
||||
|
||||
// NewNonceCaller updates the nonceCaller for this session.
|
||||
func (s *policySession) NewNonceCaller() error {
|
||||
_, err := rand.Read(s.nonceCaller.Buffer)
|
||||
return err
|
||||
}
|
||||
|
||||
// Authorize computes the authorization structure for the session.
|
||||
func (s *policySession) Authorize(cc TPMCC, parms, addNonces []byte, names []TPM2BName, _ int) (*TPMSAuthCommand, error) {
|
||||
if s.handle == TPMRHNull {
|
||||
// Session is not initialized.
|
||||
return nil, fmt.Errorf("session not initialized")
|
||||
}
|
||||
|
||||
var hmac []byte
|
||||
if s.password {
|
||||
hmac = s.auth
|
||||
} else {
|
||||
// Part 1, 19.6
|
||||
// HMAC key is (sessionKey || auth).
|
||||
var hmacKey []byte
|
||||
hmacKey = append(hmacKey, s.sessionKey...)
|
||||
hmacKey = append(hmacKey, hmacKeyFromAuthValue(s.auth)...)
|
||||
|
||||
// Compute the authorization HMAC.
|
||||
cph, err := cpHash(s.hash, cc, names, parms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hmac, err = computeHMAC(s.hash, hmacKey, cph, s.nonceCaller.Buffer, s.nonceTPM.Buffer, addNonces, s.attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
result := TPMSAuthCommand{
|
||||
Handle: s.handle,
|
||||
Nonce: s.nonceCaller,
|
||||
Attributes: s.attrs,
|
||||
Authorization: TPM2BData{
|
||||
Buffer: hmac,
|
||||
},
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// Validate valitades the response session structure for the session.
|
||||
// Updates nonceTPM from the TPM's response.
|
||||
func (s *policySession) Validate(rc TPMRC, cc TPMCC, parms []byte, _ []TPM2BName, _ int, auth *TPMSAuthResponse) error {
|
||||
// Track the new nonceTPM for the session.
|
||||
s.nonceTPM = auth.Nonce
|
||||
// Track the session being automatically flushed.
|
||||
if !auth.Attributes.ContinueSession {
|
||||
s.handle = TPMRHNull
|
||||
}
|
||||
|
||||
if s.password {
|
||||
// If we used a password, expect no nonce and no response HMAC.
|
||||
if len(auth.Nonce.Buffer) != 0 {
|
||||
return fmt.Errorf("expected empty nonce in response auth to PW policy, got %x", auth.Nonce)
|
||||
}
|
||||
if len(auth.Authorization.Buffer) != 0 {
|
||||
return fmt.Errorf("expected empty HMAC in response auth to PW policy, got %x", auth.Authorization)
|
||||
}
|
||||
} else {
|
||||
// Part 1, 19.6
|
||||
// HMAC key is (sessionKey || auth).
|
||||
var hmacKey []byte
|
||||
hmacKey = append(hmacKey, s.sessionKey...)
|
||||
hmacKey = append(hmacKey, hmacKeyFromAuthValue(s.auth)...)
|
||||
// Compute the authorization HMAC.
|
||||
rph, err := rpHash(s.hash, rc, cc, parms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mac, err := computeHMAC(s.hash, hmacKey, rph, s.nonceTPM.Buffer, s.nonceCaller.Buffer, nil, auth.Attributes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Compare the HMAC (constant time)
|
||||
if !hmac.Equal(mac, auth.Authorization.Buffer) {
|
||||
return fmt.Errorf("incorrect authorization HMAC")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEncryption returns true if this is an encryption session.
|
||||
func (s *policySession) IsEncryption() bool {
|
||||
return s.attrs.Encrypt
|
||||
}
|
||||
|
||||
// IsDecryption returns true if this is a decryption session.
|
||||
func (s *policySession) IsDecryption() bool {
|
||||
return s.attrs.Decrypt
|
||||
}
|
||||
|
||||
// Encrypt encrypts the parameter in place, if this session is used for
|
||||
// parameter decryption. Otherwise, it does not modify the parameter.
|
||||
func (s *policySession) Encrypt(parameter []byte) error {
|
||||
if !s.IsDecryption() {
|
||||
return nil
|
||||
}
|
||||
// Only AES-CFB is supported.
|
||||
bits, err := s.symmetric.KeyBits.AES()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyBytes := *bits / 8
|
||||
keyIVBytes := int(keyBytes) + 16
|
||||
var sessionValue []byte
|
||||
sessionValue = append(sessionValue, s.sessionKey...)
|
||||
sessionValue = append(sessionValue, s.auth...)
|
||||
ha, err := s.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyIV := KDFa(ha, sessionValue, "CFB", s.nonceCaller.Buffer, s.nonceTPM.Buffer, keyIVBytes*8)
|
||||
key, err := aes.NewCipher(keyIV[:keyBytes])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream := cipher.NewCFBEncrypter(key, keyIV[keyBytes:])
|
||||
stream.XORKeyStream(parameter, parameter)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the parameter in place, if this session is used for
|
||||
// parameter encryption. Otherwise, it does not modify the parameter.
|
||||
func (s *policySession) Decrypt(parameter []byte) error {
|
||||
if !s.IsEncryption() {
|
||||
return nil
|
||||
}
|
||||
// Only AES-CFB is supported.
|
||||
bits, err := s.symmetric.KeyBits.AES()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyBytes := *bits / 8
|
||||
keyIVBytes := int(keyBytes) + 16
|
||||
// Part 1, 21.1
|
||||
var sessionValue []byte
|
||||
sessionValue = append(sessionValue, s.sessionKey...)
|
||||
sessionValue = append(sessionValue, s.auth...)
|
||||
ha, err := s.hash.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyIV := KDFa(ha, sessionValue, "CFB", s.nonceTPM.Buffer, s.nonceCaller.Buffer, keyIVBytes*8)
|
||||
key, err := aes.NewCipher(keyIV[:keyBytes])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream := cipher.NewCFBDecrypter(key, keyIV[keyBytes:])
|
||||
stream.XORKeyStream(parameter, parameter)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle returns the handle value of the session.
|
||||
// If the session is created with Policy (instead of PolicySession) this will be
|
||||
// TPM_RH_NULL.
|
||||
func (s *policySession) Handle() TPMHandle {
|
||||
return s.handle
|
||||
}
|
||||
3331
vendor/github.com/google/go-tpm/tpm2/structures.go
generated
vendored
Normal file
3331
vendor/github.com/google/go-tpm/tpm2/structures.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
200
vendor/github.com/google/go-tpm/tpm2/templates.go
generated
vendored
Normal file
200
vendor/github.com/google/go-tpm/tpm2/templates.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
package tpm2
|
||||
|
||||
var (
|
||||
// RSASRKTemplate contains the TCG reference RSA-2048 SRK template.
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf
|
||||
RSASRKTemplate = TPMTPublic{
|
||||
Type: TPMAlgRSA,
|
||||
NameAlg: TPMAlgSHA256,
|
||||
ObjectAttributes: TPMAObject{
|
||||
FixedTPM: true,
|
||||
STClear: false,
|
||||
FixedParent: true,
|
||||
SensitiveDataOrigin: true,
|
||||
UserWithAuth: true,
|
||||
AdminWithPolicy: false,
|
||||
NoDA: true,
|
||||
EncryptedDuplication: false,
|
||||
Restricted: true,
|
||||
Decrypt: true,
|
||||
SignEncrypt: false,
|
||||
},
|
||||
Parameters: NewTPMUPublicParms(
|
||||
TPMAlgRSA,
|
||||
&TPMSRSAParms{
|
||||
Symmetric: TPMTSymDefObject{
|
||||
Algorithm: TPMAlgAES,
|
||||
KeyBits: NewTPMUSymKeyBits(
|
||||
TPMAlgAES,
|
||||
TPMKeyBits(128),
|
||||
),
|
||||
Mode: NewTPMUSymMode(
|
||||
TPMAlgAES,
|
||||
TPMAlgCFB,
|
||||
),
|
||||
},
|
||||
KeyBits: 2048,
|
||||
},
|
||||
),
|
||||
Unique: NewTPMUPublicID(
|
||||
TPMAlgRSA,
|
||||
&TPM2BPublicKeyRSA{
|
||||
Buffer: make([]byte, 256),
|
||||
},
|
||||
),
|
||||
}
|
||||
// RSAEKTemplate contains the TCG reference RSA-2048 EK template.
|
||||
RSAEKTemplate = TPMTPublic{
|
||||
Type: TPMAlgRSA,
|
||||
NameAlg: TPMAlgSHA256,
|
||||
ObjectAttributes: TPMAObject{
|
||||
FixedTPM: true,
|
||||
STClear: false,
|
||||
FixedParent: true,
|
||||
SensitiveDataOrigin: true,
|
||||
UserWithAuth: false,
|
||||
AdminWithPolicy: true,
|
||||
NoDA: false,
|
||||
EncryptedDuplication: false,
|
||||
Restricted: true,
|
||||
Decrypt: true,
|
||||
SignEncrypt: false,
|
||||
},
|
||||
AuthPolicy: TPM2BDigest{
|
||||
Buffer: []byte{
|
||||
// TPM2_PolicySecret(RH_ENDORSEMENT)
|
||||
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xB3, 0xF8,
|
||||
0x1A, 0x90, 0xCC, 0x8D, 0x46, 0xA5, 0xD7, 0x24,
|
||||
0xFD, 0x52, 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64,
|
||||
0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, 0x69, 0xAA,
|
||||
},
|
||||
},
|
||||
Parameters: NewTPMUPublicParms(
|
||||
TPMAlgRSA,
|
||||
&TPMSRSAParms{
|
||||
Symmetric: TPMTSymDefObject{
|
||||
Algorithm: TPMAlgAES,
|
||||
KeyBits: NewTPMUSymKeyBits(
|
||||
TPMAlgAES,
|
||||
TPMKeyBits(128),
|
||||
),
|
||||
Mode: NewTPMUSymMode(
|
||||
TPMAlgAES,
|
||||
TPMAlgCFB,
|
||||
),
|
||||
},
|
||||
KeyBits: 2048,
|
||||
},
|
||||
),
|
||||
Unique: NewTPMUPublicID(
|
||||
TPMAlgRSA,
|
||||
&TPM2BPublicKeyRSA{
|
||||
Buffer: make([]byte, 256),
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
// ECCSRKTemplate contains the TCG reference ECC-P256 SRK template.
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf
|
||||
ECCSRKTemplate = TPMTPublic{
|
||||
Type: TPMAlgECC,
|
||||
NameAlg: TPMAlgSHA256,
|
||||
ObjectAttributes: TPMAObject{
|
||||
FixedTPM: true,
|
||||
STClear: false,
|
||||
FixedParent: true,
|
||||
SensitiveDataOrigin: true,
|
||||
UserWithAuth: true,
|
||||
AdminWithPolicy: false,
|
||||
NoDA: true,
|
||||
EncryptedDuplication: false,
|
||||
Restricted: true,
|
||||
Decrypt: true,
|
||||
SignEncrypt: false,
|
||||
},
|
||||
Parameters: NewTPMUPublicParms(
|
||||
TPMAlgECC,
|
||||
&TPMSECCParms{
|
||||
Symmetric: TPMTSymDefObject{
|
||||
Algorithm: TPMAlgAES,
|
||||
KeyBits: NewTPMUSymKeyBits(
|
||||
TPMAlgAES,
|
||||
TPMKeyBits(128),
|
||||
),
|
||||
Mode: NewTPMUSymMode(
|
||||
TPMAlgAES,
|
||||
TPMAlgCFB,
|
||||
),
|
||||
},
|
||||
CurveID: TPMECCNistP256,
|
||||
},
|
||||
),
|
||||
Unique: NewTPMUPublicID(
|
||||
TPMAlgECC,
|
||||
&TPMSECCPoint{
|
||||
X: TPM2BECCParameter{
|
||||
Buffer: make([]byte, 32),
|
||||
},
|
||||
Y: TPM2BECCParameter{
|
||||
Buffer: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
// ECCEKTemplate contains the TCG reference ECC-P256 EK template.
|
||||
ECCEKTemplate = TPMTPublic{
|
||||
Type: TPMAlgECC,
|
||||
NameAlg: TPMAlgSHA256,
|
||||
ObjectAttributes: TPMAObject{
|
||||
FixedTPM: true,
|
||||
STClear: false,
|
||||
FixedParent: true,
|
||||
SensitiveDataOrigin: true,
|
||||
UserWithAuth: false,
|
||||
AdminWithPolicy: true,
|
||||
NoDA: false,
|
||||
EncryptedDuplication: false,
|
||||
Restricted: true,
|
||||
Decrypt: true,
|
||||
SignEncrypt: false,
|
||||
},
|
||||
AuthPolicy: TPM2BDigest{
|
||||
Buffer: []byte{
|
||||
// TPM2_PolicySecret(RH_ENDORSEMENT)
|
||||
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xB3, 0xF8,
|
||||
0x1A, 0x90, 0xCC, 0x8D, 0x46, 0xA5, 0xD7, 0x24,
|
||||
0xFD, 0x52, 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64,
|
||||
0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, 0x69, 0xAA,
|
||||
},
|
||||
},
|
||||
Parameters: NewTPMUPublicParms(
|
||||
TPMAlgECC,
|
||||
&TPMSECCParms{
|
||||
Symmetric: TPMTSymDefObject{
|
||||
Algorithm: TPMAlgAES,
|
||||
KeyBits: NewTPMUSymKeyBits(
|
||||
TPMAlgAES,
|
||||
TPMKeyBits(128),
|
||||
),
|
||||
Mode: NewTPMUSymMode(
|
||||
TPMAlgAES,
|
||||
TPMAlgCFB,
|
||||
),
|
||||
},
|
||||
CurveID: TPMECCNistP256,
|
||||
},
|
||||
),
|
||||
Unique: NewTPMUPublicID(
|
||||
TPMAlgECC,
|
||||
&TPMSECCPoint{
|
||||
X: TPM2BECCParameter{
|
||||
Buffer: make([]byte, 32),
|
||||
},
|
||||
Y: TPM2BECCParameter{
|
||||
Buffer: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
)
|
||||
2258
vendor/github.com/google/go-tpm/tpm2/tpm2.go
generated
vendored
Normal file
2258
vendor/github.com/google/go-tpm/tpm2/tpm2.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
83
vendor/github.com/google/go-tpm/tpm2/tpm2b.go
generated
vendored
Normal file
83
vendor/github.com/google/go-tpm/tpm2/tpm2b.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package tpm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// TPM2B is a helper type for all sized TPM structures. It can be instantiated with either a raw byte buffer or the actual struct.
|
||||
type TPM2B[T Marshallable, P interface {
|
||||
*T
|
||||
Unmarshallable
|
||||
}] struct {
|
||||
contents *T
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
// New2B creates a new TPM2B containing the given contents.
|
||||
func New2B[T Marshallable, P interface {
|
||||
*T
|
||||
Unmarshallable
|
||||
}](t T) TPM2B[T, P] {
|
||||
return TPM2B[T, P]{contents: &t}
|
||||
}
|
||||
|
||||
// BytesAs2B creates a new TPM2B containing the given byte array.
|
||||
func BytesAs2B[T Marshallable, P interface {
|
||||
*T
|
||||
Unmarshallable
|
||||
}](b []byte) TPM2B[T, P] {
|
||||
return TPM2B[T, P]{buffer: b}
|
||||
}
|
||||
|
||||
// Contents returns the structured contents of the TPM2B.
|
||||
// It can fail if the TPM2B was instantiated with an invalid byte buffer.
|
||||
func (value *TPM2B[T, P]) Contents() (*T, error) {
|
||||
if value.contents != nil {
|
||||
return value.contents, nil
|
||||
}
|
||||
if value.buffer == nil {
|
||||
return nil, fmt.Errorf("TPMB had no contents or buffer")
|
||||
}
|
||||
contents, err := Unmarshal[T, P](value.buffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cache the result
|
||||
value.contents = (*T)(contents)
|
||||
return value.contents, nil
|
||||
}
|
||||
|
||||
// Bytes returns the inner contents of the TPM2B as a byte array, not including the length field.
|
||||
func (value *TPM2B[T, P]) Bytes() []byte {
|
||||
if value.buffer != nil {
|
||||
return value.buffer
|
||||
}
|
||||
if value.contents == nil {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// Cache the result
|
||||
value.buffer = Marshal(*value.contents)
|
||||
return value.buffer
|
||||
}
|
||||
|
||||
// marshal implements the tpm2.Marshallable interface.
|
||||
func (value TPM2B[T, P]) marshal(buf *bytes.Buffer) {
|
||||
b := value.Bytes()
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(b)))
|
||||
buf.Write(b)
|
||||
}
|
||||
|
||||
// unmarshal implements the tpm2.Unmarshallable interface.
|
||||
// Note: the structure contents are not validated during unmarshalling.
|
||||
func (value *TPM2B[T, P]) unmarshal(buf *bytes.Buffer) error {
|
||||
var size uint16
|
||||
binary.Read(buf, binary.BigEndian, &size)
|
||||
value.contents = nil
|
||||
value.buffer = make([]byte, size)
|
||||
_, err := io.ReadAtLeast(buf, value.buffer, int(size))
|
||||
return err
|
||||
}
|
||||
22
vendor/github.com/google/go-tpm/tpm2/transport/open_other.go
generated
vendored
Normal file
22
vendor/github.com/google/go-tpm/tpm2/transport/open_other.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
//go:build !windows
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
legacy "github.com/google/go-tpm/legacy/tpm2"
|
||||
)
|
||||
|
||||
// OpenTPM opens the TPM at the given path. If no path is provided, it will
|
||||
// attempt to use reasonable defaults.
|
||||
//
|
||||
// Deprecated: Please use the individual transport packages (e.g.,
|
||||
// go-tpm/tpm2/transport/linuxtpm).
|
||||
func OpenTPM(path ...string) (TPMCloser, error) {
|
||||
rwc, err := legacy.OpenTPM(path...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &wrappedRWC{
|
||||
transport: rwc,
|
||||
}, nil
|
||||
}
|
||||
21
vendor/github.com/google/go-tpm/tpm2/transport/open_windows.go
generated
vendored
Normal file
21
vendor/github.com/google/go-tpm/tpm2/transport/open_windows.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build windows
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
legacy "github.com/google/go-tpm/legacy/tpm2"
|
||||
)
|
||||
|
||||
// OpenTPM opens the local system TPM.
|
||||
//
|
||||
// Deprecated: Please use the individual transport packages (e.g.,
|
||||
// go-tpm/tpm2/transport/windowstpm).
|
||||
func OpenTPM() (TPMCloser, error) {
|
||||
rwc, err := legacy.OpenTPM()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &wrappedRWC{
|
||||
transport: rwc,
|
||||
}, nil
|
||||
}
|
||||
90
vendor/github.com/google/go-tpm/tpm2/transport/tpm.go
generated
vendored
Normal file
90
vendor/github.com/google/go-tpm/tpm2/transport/tpm.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
// Package transport implements types for physically talking to TPMs.
|
||||
package transport
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
)
|
||||
|
||||
// TPM represents a logical connection to a TPM.
|
||||
type TPM interface {
|
||||
Send(input []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// TPMCloser represents a logical connection to a TPM and you can close it.
|
||||
type TPMCloser interface {
|
||||
TPM
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// wrappedRW represents a struct that wraps an io.ReadWriter
|
||||
// to a transport.TPM to be compatible with tpmdirect.
|
||||
type wrappedRW struct {
|
||||
transport io.ReadWriter
|
||||
}
|
||||
|
||||
// wrappedRWC represents a struct that wraps an io.ReadWriteCloser
|
||||
// to a transport.TPM to be compatible with tpmdirect.
|
||||
type wrappedRWC struct {
|
||||
transport io.ReadWriteCloser
|
||||
}
|
||||
|
||||
// wrappedTPM represents a struct that wraps a transport.TPM's underlying
|
||||
// transport to use with legacy code that expects an io.ReadWriter.
|
||||
type wrappedTPM struct {
|
||||
response []byte
|
||||
tpm TPM
|
||||
}
|
||||
|
||||
// FromReadWriter takes in a io.ReadWriter and returns a
|
||||
// transport.TPM wrapping the io.ReadWriter.
|
||||
func FromReadWriter(rw io.ReadWriter) TPM {
|
||||
return &wrappedRW{transport: rw}
|
||||
}
|
||||
|
||||
// FromReadWriteCloser takes in a io.ReadWriteCloser and returns a
|
||||
// transport.TPMCloser wrapping the io.ReadWriteCloser.
|
||||
func FromReadWriteCloser(rwc io.ReadWriteCloser) TPMCloser {
|
||||
return &wrappedRWC{transport: rwc}
|
||||
}
|
||||
|
||||
// ToReadWriter takes in a transport TPM and returns an
|
||||
// io.ReadWriter wrapping the transport TPM.
|
||||
func ToReadWriter(tpm TPM) io.ReadWriter {
|
||||
return &wrappedTPM{tpm: tpm}
|
||||
}
|
||||
|
||||
// Read copies t.response into the p buffer and return the appropriate length.
|
||||
func (t *wrappedTPM) Read(p []byte) (int, error) {
|
||||
n := copy(p, t.response)
|
||||
t.response = t.response[n:]
|
||||
if len(t.response) == 0 {
|
||||
return n, io.EOF
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Write implements the io.ReadWriter interface.
|
||||
func (t *wrappedTPM) Write(p []byte) (n int, err error) {
|
||||
t.response, err = t.tpm.Send(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Send implements the TPM interface.
|
||||
func (t *wrappedRW) Send(input []byte) ([]byte, error) {
|
||||
return tpmutil.RunCommandRaw(t.transport, input)
|
||||
}
|
||||
|
||||
// Send implements the TPM interface.
|
||||
func (t *wrappedRWC) Send(input []byte) ([]byte, error) {
|
||||
return tpmutil.RunCommandRaw(t.transport, input)
|
||||
}
|
||||
|
||||
// Close implements the TPM interface.
|
||||
func (t *wrappedRWC) Close() error {
|
||||
return t.transport.Close()
|
||||
}
|
||||
211
vendor/github.com/google/go-tpm/tpmutil/encoding.go
generated
vendored
Normal file
211
vendor/github.com/google/go-tpm/tpmutil/encoding.go
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
selfMarshalerType = reflect.TypeOf((*SelfMarshaler)(nil)).Elem()
|
||||
handlesAreaType = reflect.TypeOf((*[]Handle)(nil))
|
||||
)
|
||||
|
||||
// packWithHeader takes a header and a sequence of elements that are either of
|
||||
// fixed length or slices of fixed-length types and packs them into a single
|
||||
// byte array using binary.Write. It updates the CommandHeader to have the right
|
||||
// length.
|
||||
func packWithHeader(ch commandHeader, cmd ...interface{}) ([]byte, error) {
|
||||
hdrSize := binary.Size(ch)
|
||||
body, err := Pack(cmd...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't pack message body: %v", err)
|
||||
}
|
||||
bodySize := len(body)
|
||||
ch.Size = uint32(hdrSize + bodySize)
|
||||
header, err := Pack(ch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't pack message header: %v", err)
|
||||
}
|
||||
return append(header, body...), nil
|
||||
}
|
||||
|
||||
// Pack encodes a set of elements into a single byte array, using
|
||||
// encoding/binary. This means that all the elements must be encodeable
|
||||
// according to the rules of encoding/binary.
|
||||
//
|
||||
// It has one difference from encoding/binary: it encodes byte slices with a
|
||||
// prepended length, to match how the TPM encodes variable-length arrays. If
|
||||
// you wish to add a byte slice without length prefix, use RawBytes.
|
||||
func Pack(elts ...interface{}) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := packType(buf, elts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// tryMarshal attempts to use a TPMMarshal() method defined on the type
|
||||
// to pack v into buf. True is returned if the method exists and the
|
||||
// marshal was attempted.
|
||||
func tryMarshal(buf io.Writer, v reflect.Value) (bool, error) {
|
||||
t := v.Type()
|
||||
if t.Implements(selfMarshalerType) {
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
return true, fmt.Errorf("cannot call TPMMarshal on a nil pointer of type %T", v)
|
||||
}
|
||||
return true, v.Interface().(SelfMarshaler).TPMMarshal(buf)
|
||||
}
|
||||
|
||||
// We might have a non-pointer struct field, but we dont have a
|
||||
// pointer with which to implement the interface.
|
||||
// If the pointer of the type implements the interface, we should be
|
||||
// able to construct a value to call TPMMarshal() with.
|
||||
// TODO(awly): Try and avoid blowing away private data by using Addr() instead of Set()
|
||||
if reflect.PtrTo(t).Implements(selfMarshalerType) {
|
||||
tmp := reflect.New(t)
|
||||
tmp.Elem().Set(v)
|
||||
return true, tmp.Interface().(SelfMarshaler).TPMMarshal(buf)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func packValue(buf io.Writer, v reflect.Value) error {
|
||||
if v.Type() == handlesAreaType {
|
||||
v = v.Convert(reflect.TypeOf((*handleList)(nil)))
|
||||
}
|
||||
if canMarshal, err := tryMarshal(buf, v); canMarshal {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr:
|
||||
if v.IsNil() {
|
||||
return fmt.Errorf("cannot pack nil %s", v.Type().String())
|
||||
}
|
||||
return packValue(buf, v.Elem())
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if err := packValue(buf, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
return binary.Write(buf, binary.BigEndian, v.Interface())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func packType(buf io.Writer, elts ...interface{}) error {
|
||||
for _, e := range elts {
|
||||
if err := packValue(buf, reflect.ValueOf(e)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// tryUnmarshal attempts to use TPMUnmarshal() to perform the
|
||||
// unpack, if the given value implements SelfMarshaler.
|
||||
// True is returned if v implements SelfMarshaler & TPMUnmarshal
|
||||
// was called, along with an error returned from TPMUnmarshal.
|
||||
func tryUnmarshal(buf io.Reader, v reflect.Value) (bool, error) {
|
||||
t := v.Type()
|
||||
if t.Implements(selfMarshalerType) {
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
return true, fmt.Errorf("cannot call TPMUnmarshal on a nil pointer")
|
||||
}
|
||||
return true, v.Interface().(SelfMarshaler).TPMUnmarshal(buf)
|
||||
}
|
||||
|
||||
// We might have a non-pointer struct field, which is addressable,
|
||||
// If the pointer of the type implements the interface, and the
|
||||
// value is addressable, we should be able to call TPMUnmarshal().
|
||||
if v.CanAddr() && reflect.PtrTo(t).Implements(selfMarshalerType) {
|
||||
return true, v.Addr().Interface().(SelfMarshaler).TPMUnmarshal(buf)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Unpack is a convenience wrapper around UnpackBuf. Unpack returns the number
|
||||
// of bytes read from b to fill elts and error, if any.
|
||||
func Unpack(b []byte, elts ...interface{}) (int, error) {
|
||||
buf := bytes.NewBuffer(b)
|
||||
err := UnpackBuf(buf, elts...)
|
||||
read := len(b) - buf.Len()
|
||||
return read, err
|
||||
}
|
||||
|
||||
func unpackValue(buf io.Reader, v reflect.Value) error {
|
||||
if v.Type() == handlesAreaType {
|
||||
v = v.Convert(reflect.TypeOf((*handleList)(nil)))
|
||||
}
|
||||
if didUnmarshal, err := tryUnmarshal(buf, v); didUnmarshal {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr:
|
||||
if v.IsNil() {
|
||||
return fmt.Errorf("cannot unpack nil %s", v.Type().String())
|
||||
}
|
||||
return unpackValue(buf, v.Elem())
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if err := unpackValue(buf, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
// binary.Read can only set pointer values, so we need to take the address.
|
||||
if !v.CanAddr() {
|
||||
return fmt.Errorf("cannot unpack unaddressable leaf type %q", v.Type().String())
|
||||
}
|
||||
return binary.Read(buf, binary.BigEndian, v.Addr().Interface())
|
||||
}
|
||||
}
|
||||
|
||||
// UnpackBuf recursively unpacks types from a reader just as encoding/binary
|
||||
// does under binary.BigEndian, but with one difference: it unpacks a byte
|
||||
// slice by first reading an integer with lengthPrefixSize bytes, then reading
|
||||
// that many bytes. It assumes that incoming values are pointers to values so
|
||||
// that, e.g., underlying slices can be resized as needed.
|
||||
func UnpackBuf(buf io.Reader, elts ...interface{}) error {
|
||||
for _, e := range elts {
|
||||
v := reflect.ValueOf(e)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("non-pointer value %q passed to UnpackBuf", v.Type().String())
|
||||
}
|
||||
if v.IsNil() {
|
||||
return errors.New("nil pointer passed to UnpackBuf")
|
||||
}
|
||||
|
||||
if err := unpackValue(buf, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
10
vendor/github.com/google/go-tpm/tpmutil/poll_other.go
generated
vendored
Normal file
10
vendor/github.com/google/go-tpm/tpmutil/poll_other.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
//go:build !linux && !darwin
|
||||
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Not implemented on Windows.
|
||||
func poll(_ *os.File) error { return nil }
|
||||
32
vendor/github.com/google/go-tpm/tpmutil/poll_unix.go
generated
vendored
Normal file
32
vendor/github.com/google/go-tpm/tpmutil/poll_unix.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
//go:build linux || darwin
|
||||
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// poll blocks until the file descriptor is ready for reading or an error occurs.
|
||||
func poll(f *os.File) error {
|
||||
var (
|
||||
fds = []unix.PollFd{{
|
||||
Fd: int32(f.Fd()),
|
||||
Events: 0x1, // POLLIN
|
||||
}}
|
||||
timeout = -1 // Indefinite timeout
|
||||
)
|
||||
|
||||
if _, err := unix.Poll(fds, timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Revents is filled in by the kernel.
|
||||
// If the expected event happened, Revents should match Events.
|
||||
if fds[0].Revents != fds[0].Events {
|
||||
return fmt.Errorf("unexpected poll Revents 0x%x", fds[0].Revents)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
113
vendor/github.com/google/go-tpm/tpmutil/run.go
generated
vendored
Normal file
113
vendor/github.com/google/go-tpm/tpmutil/run.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package tpmutil provides common utility functions for both TPM 1.2 and TPM
|
||||
// 2.0 devices.
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// maxTPMResponse is the largest possible response from the TPM. We need to know
|
||||
// this because we don't always know the length of the TPM response, and
|
||||
// /dev/tpm insists on giving it all back in a single value rather than
|
||||
// returning a header and a body in separate responses.
|
||||
const maxTPMResponse = 4096
|
||||
|
||||
// RunCommandRaw executes the given raw command and returns the raw response.
|
||||
// Does not check the response code except to execute retry logic.
|
||||
func RunCommandRaw(rw io.ReadWriter, inb []byte) ([]byte, error) {
|
||||
if rw == nil {
|
||||
return nil, errors.New("nil TPM handle")
|
||||
}
|
||||
|
||||
// f(t) = (2^t)ms, up to 2s
|
||||
var backoffFac uint
|
||||
var rh responseHeader
|
||||
var outb []byte
|
||||
|
||||
for {
|
||||
if _, err := rw.Write(inb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the TPM is a real device, it may not be ready for reading
|
||||
// immediately after writing the command. Wait until the file
|
||||
// descriptor is ready to be read from.
|
||||
if f, ok := rw.(*os.File); ok {
|
||||
if err := poll(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
outb = make([]byte, maxTPMResponse)
|
||||
outlen, err := rw.Read(outb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Resize the buffer to match the amount read from the TPM.
|
||||
outb = outb[:outlen]
|
||||
|
||||
_, err = Unpack(outb, &rh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If TPM is busy, retry the command after waiting a few ms.
|
||||
if rh.Res == RCRetry {
|
||||
if backoffFac < 11 {
|
||||
dur := (1 << backoffFac) * time.Millisecond
|
||||
time.Sleep(dur)
|
||||
backoffFac++
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return outb, nil
|
||||
}
|
||||
|
||||
// RunCommand executes cmd with given tag and arguments. Returns TPM response
|
||||
// body (without response header) and response code from the header. Returned
|
||||
// error may be nil if response code is not RCSuccess; caller should check
|
||||
// both.
|
||||
func RunCommand(rw io.ReadWriter, tag Tag, cmd Command, in ...interface{}) ([]byte, ResponseCode, error) {
|
||||
inb, err := packWithHeader(commandHeader{tag, 0, cmd}, in...)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
outb, err := RunCommandRaw(rw, inb)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var rh responseHeader
|
||||
read, err := Unpack(outb, &rh)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if rh.Res != RCSuccess {
|
||||
return nil, rh.Res, nil
|
||||
}
|
||||
|
||||
return outb[read:], rh.Res, nil
|
||||
}
|
||||
111
vendor/github.com/google/go-tpm/tpmutil/run_other.go
generated
vendored
Normal file
111
vendor/github.com/google/go-tpm/tpmutil/run_other.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
//go:build !windows
|
||||
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
// OpenTPM opens a channel to the TPM at the given path. If the file is a
|
||||
// device, then it treats it like a normal TPM device, and if the file is a
|
||||
// Unix domain socket, then it opens a connection to the socket.
|
||||
func OpenTPM(path string) (io.ReadWriteCloser, error) {
|
||||
// If it's a regular file, then open it
|
||||
var rwc io.ReadWriteCloser
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fi.Mode()&os.ModeDevice != 0 {
|
||||
var f *os.File
|
||||
f, err = os.OpenFile(path, os.O_RDWR, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rwc = io.ReadWriteCloser(f)
|
||||
} else if fi.Mode()&os.ModeSocket != 0 {
|
||||
rwc = NewEmulatorReadWriteCloser(path)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unsupported TPM file mode %s", fi.Mode().String())
|
||||
}
|
||||
|
||||
return rwc, nil
|
||||
}
|
||||
|
||||
// dialer abstracts the net.Dial call so test code can provide its own net.Conn
|
||||
// implementation.
|
||||
type dialer func(network, path string) (net.Conn, error)
|
||||
|
||||
// EmulatorReadWriteCloser manages connections with a TPM emulator over a Unix
|
||||
// domain socket. These emulators often operate in a write/read/disconnect
|
||||
// sequence, so the Write method always connects, and the Read method always
|
||||
// closes. EmulatorReadWriteCloser is not thread safe.
|
||||
type EmulatorReadWriteCloser struct {
|
||||
path string
|
||||
conn net.Conn
|
||||
dialer dialer
|
||||
}
|
||||
|
||||
// NewEmulatorReadWriteCloser stores information about a Unix domain socket to
|
||||
// write to and read from.
|
||||
func NewEmulatorReadWriteCloser(path string) *EmulatorReadWriteCloser {
|
||||
return &EmulatorReadWriteCloser{
|
||||
path: path,
|
||||
dialer: net.Dial,
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements io.Reader by reading from the Unix domain socket and closing
|
||||
// it.
|
||||
func (erw *EmulatorReadWriteCloser) Read(p []byte) (int, error) {
|
||||
// Read is always the second operation in a Write/Read sequence.
|
||||
if erw.conn == nil {
|
||||
return 0, fmt.Errorf("must call Write then Read in an alternating sequence")
|
||||
}
|
||||
n, err := erw.conn.Read(p)
|
||||
erw.conn.Close()
|
||||
erw.conn = nil
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Write implements io.Writer by connecting to the Unix domain socket and
|
||||
// writing.
|
||||
func (erw *EmulatorReadWriteCloser) Write(p []byte) (int, error) {
|
||||
if erw.conn != nil {
|
||||
return 0, fmt.Errorf("must call Write then Read in an alternating sequence")
|
||||
}
|
||||
var err error
|
||||
erw.conn, err = erw.dialer("unix", erw.path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return erw.conn.Write(p)
|
||||
}
|
||||
|
||||
// Close implements io.Closer by closing the Unix domain socket if one is open.
|
||||
func (erw *EmulatorReadWriteCloser) Close() error {
|
||||
if erw.conn == nil {
|
||||
return fmt.Errorf("cannot call Close when no connection is open")
|
||||
}
|
||||
err := erw.conn.Close()
|
||||
erw.conn = nil
|
||||
return err
|
||||
}
|
||||
84
vendor/github.com/google/go-tpm/tpmutil/run_windows.go
generated
vendored
Normal file
84
vendor/github.com/google/go-tpm/tpmutil/run_windows.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/google/go-tpm/tpmutil/tbs"
|
||||
)
|
||||
|
||||
// winTPMBuffer is a ReadWriteCloser to access the TPM in Windows.
|
||||
type winTPMBuffer struct {
|
||||
context tbs.Context
|
||||
outBuffer []byte
|
||||
}
|
||||
|
||||
// Executes the TPM command specified by commandBuffer (at Normal Priority), returning the number
|
||||
// of bytes in the command and any error code returned by executing the TPM command. Command
|
||||
// response can be read by calling Read().
|
||||
func (rwc *winTPMBuffer) Write(commandBuffer []byte) (int, error) {
|
||||
// TPM spec defines longest possible response to be maxTPMResponse.
|
||||
rwc.outBuffer = rwc.outBuffer[:maxTPMResponse]
|
||||
|
||||
outBufferLen, err := rwc.context.SubmitCommand(
|
||||
tbs.NormalPriority,
|
||||
commandBuffer,
|
||||
rwc.outBuffer,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
rwc.outBuffer = rwc.outBuffer[:0]
|
||||
return 0, err
|
||||
}
|
||||
// Shrink outBuffer so it is length of response.
|
||||
rwc.outBuffer = rwc.outBuffer[:outBufferLen]
|
||||
return len(commandBuffer), nil
|
||||
}
|
||||
|
||||
// Provides TPM response from the command called in the last Write call.
|
||||
func (rwc *winTPMBuffer) Read(responseBuffer []byte) (int, error) {
|
||||
if len(rwc.outBuffer) == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
lenCopied := copy(responseBuffer, rwc.outBuffer)
|
||||
// Cut out the piece of slice which was just read out, maintaining original slice capacity.
|
||||
rwc.outBuffer = append(rwc.outBuffer[:0], rwc.outBuffer[lenCopied:]...)
|
||||
return lenCopied, nil
|
||||
}
|
||||
|
||||
func (rwc *winTPMBuffer) Close() error {
|
||||
return rwc.context.Close()
|
||||
}
|
||||
|
||||
// OpenTPM creates a new instance of a ReadWriteCloser which can interact with a
|
||||
// Windows TPM.
|
||||
func OpenTPM() (io.ReadWriteCloser, error) {
|
||||
tpmContext, err := tbs.CreateContext(tbs.TPMVersion20, tbs.IncludeTPM12|tbs.IncludeTPM20)
|
||||
rwc := &winTPMBuffer{
|
||||
context: tpmContext,
|
||||
outBuffer: make([]byte, 0, maxTPMResponse),
|
||||
}
|
||||
return rwc, err
|
||||
}
|
||||
|
||||
// FromContext creates a new instance of a ReadWriteCloser which can
|
||||
// interact with a Windows TPM, using the specified TBS handle.
|
||||
func FromContext(ctx tbs.Context) io.ReadWriteCloser {
|
||||
return &winTPMBuffer{
|
||||
context: ctx,
|
||||
outBuffer: make([]byte, 0, maxTPMResponse),
|
||||
}
|
||||
}
|
||||
195
vendor/github.com/google/go-tpm/tpmutil/structures.go
generated
vendored
Normal file
195
vendor/github.com/google/go-tpm/tpmutil/structures.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
package tpmutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// maxBytesBufferSize sets a sane upper bound on the size of a U32Bytes
|
||||
// buffer. This limit exists to prevent a maliciously large size prefix
|
||||
// from resulting in a massive memory allocation, potentially causing
|
||||
// an OOM condition on the system.
|
||||
// We expect no buffer from a TPM to approach 1Mb in size.
|
||||
const maxBytesBufferSize uint32 = 1024 * 1024 // 1Mb.
|
||||
|
||||
// RawBytes is for Pack and RunCommand arguments that are already encoded.
|
||||
// Compared to []byte, RawBytes will not be prepended with slice length during
|
||||
// encoding.
|
||||
type RawBytes []byte
|
||||
|
||||
// U16Bytes is a byte slice with a 16-bit header
|
||||
type U16Bytes []byte
|
||||
|
||||
// TPMMarshal packs U16Bytes
|
||||
func (b *U16Bytes) TPMMarshal(out io.Writer) error {
|
||||
size := len([]byte(*b))
|
||||
if err := binary.Write(out, binary.BigEndian, uint16(size)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := out.Write(*b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != size {
|
||||
return fmt.Errorf("unable to write all contents of U16Bytes")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TPMUnmarshal unpacks a U16Bytes
|
||||
func (b *U16Bytes) TPMUnmarshal(in io.Reader) error {
|
||||
var tmpSize uint16
|
||||
if err := binary.Read(in, binary.BigEndian, &tmpSize); err != nil {
|
||||
return err
|
||||
}
|
||||
size := int(tmpSize)
|
||||
|
||||
if len(*b) >= size {
|
||||
*b = (*b)[:size]
|
||||
} else {
|
||||
*b = append(*b, make([]byte, size-len(*b))...)
|
||||
}
|
||||
|
||||
n, err := in.Read(*b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != size {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// U32Bytes is a byte slice with a 32-bit header
|
||||
type U32Bytes []byte
|
||||
|
||||
// TPMMarshal packs U32Bytes
|
||||
func (b *U32Bytes) TPMMarshal(out io.Writer) error {
|
||||
size := len([]byte(*b))
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(size)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := out.Write(*b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != size {
|
||||
return fmt.Errorf("unable to write all contents of U32Bytes")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TPMUnmarshal unpacks a U32Bytes
|
||||
func (b *U32Bytes) TPMUnmarshal(in io.Reader) error {
|
||||
var tmpSize uint32
|
||||
if err := binary.Read(in, binary.BigEndian, &tmpSize); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tmpSize > maxBytesBufferSize {
|
||||
return bytes.ErrTooLarge
|
||||
}
|
||||
// We can now safely cast to an int on 32-bit or 64-bit machines
|
||||
size := int(tmpSize)
|
||||
|
||||
if len(*b) >= size {
|
||||
*b = (*b)[:size]
|
||||
} else {
|
||||
*b = append(*b, make([]byte, size-len(*b))...)
|
||||
}
|
||||
|
||||
n, err := in.Read(*b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != size {
|
||||
return fmt.Errorf("unable to read all contents in to U32Bytes")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tag is a command tag.
|
||||
type Tag uint16
|
||||
|
||||
// Command is an identifier of a TPM command.
|
||||
type Command uint32
|
||||
|
||||
// A commandHeader is the header for a TPM command.
|
||||
type commandHeader struct {
|
||||
Tag Tag
|
||||
Size uint32
|
||||
Cmd Command
|
||||
}
|
||||
|
||||
// ResponseCode is a response code returned by TPM.
|
||||
type ResponseCode uint32
|
||||
|
||||
// RCSuccess is response code for successful command. Identical for TPM 1.2 and
|
||||
// 2.0.
|
||||
const RCSuccess ResponseCode = 0x000
|
||||
|
||||
// RCRetry is response code for TPM is busy.
|
||||
const RCRetry ResponseCode = 0x922
|
||||
|
||||
// A responseHeader is a header for TPM responses.
|
||||
type responseHeader struct {
|
||||
Tag Tag
|
||||
Size uint32
|
||||
Res ResponseCode
|
||||
}
|
||||
|
||||
// A Handle is a reference to a TPM object.
|
||||
type Handle uint32
|
||||
|
||||
// HandleValue returns the handle value. This behavior is intended to satisfy
|
||||
// an interface that can be implemented by other, more complex types as well.
|
||||
func (h Handle) HandleValue() uint32 {
|
||||
return uint32(h)
|
||||
}
|
||||
|
||||
type handleList []Handle
|
||||
|
||||
func (l *handleList) TPMMarshal(_ io.Writer) error {
|
||||
return fmt.Errorf("TPMMarhsal on []Handle is not supported yet")
|
||||
}
|
||||
|
||||
func (l *handleList) TPMUnmarshal(in io.Reader) error {
|
||||
var numHandles uint16
|
||||
if err := binary.Read(in, binary.BigEndian, &numHandles); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make len(e) match size exactly.
|
||||
size := int(numHandles)
|
||||
if len(*l) >= size {
|
||||
*l = (*l)[:size]
|
||||
} else {
|
||||
*l = append(*l, make([]Handle, size-len(*l))...)
|
||||
}
|
||||
return binary.Read(in, binary.BigEndian, *l)
|
||||
}
|
||||
|
||||
// SelfMarshaler allows custom types to override default encoding/decoding
|
||||
// behavior in Pack, Unpack and UnpackBuf.
|
||||
type SelfMarshaler interface {
|
||||
TPMMarshal(out io.Writer) error
|
||||
TPMUnmarshal(in io.Reader) error
|
||||
}
|
||||
267
vendor/github.com/google/go-tpm/tpmutil/tbs/tbs_windows.go
generated
vendored
Normal file
267
vendor/github.com/google/go-tpm/tpmutil/tbs/tbs_windows.go
generated
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
// Copyright (c) 2018, Google LLC All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package tbs provides an low-level interface directly mapping to Windows
|
||||
// Tbs.dll system library commands:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/TBS/tpm-base-services-portal
|
||||
// Public field descriptions contain links to the high-level Windows documentation.
|
||||
package tbs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Context references the current TPM context
|
||||
type Context uintptr
|
||||
|
||||
// Version of TPM being used by the application.
|
||||
type Version uint32
|
||||
|
||||
// Flag indicates TPM versions that are supported by the application.
|
||||
type Flag uint32
|
||||
|
||||
// CommandPriority is used to determine which pending command to submit whenever the TPM is free.
|
||||
type CommandPriority uint32
|
||||
|
||||
// Command parameters:
|
||||
// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/shared/tbs.h
|
||||
const (
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/ns-tbs-tdtbs_context_params2
|
||||
// OR flags to use multiple.
|
||||
RequestRaw Flag = 1 << iota // Add flag to request raw context
|
||||
IncludeTPM12 // Add flag to support TPM 1.2
|
||||
IncludeTPM20 // Add flag to support TPM 2
|
||||
|
||||
TPMVersion12 Version = 1 // For TPM 1.2 applications
|
||||
TPMVersion20 Version = 2 // For TPM 2 applications or applications using multiple TPM versions
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/tbs/command-scheduling
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsip_submit_command#parameters
|
||||
LowPriority CommandPriority = 100 // For low priority application use
|
||||
NormalPriority CommandPriority = 200 // For normal priority application use
|
||||
HighPriority CommandPriority = 300 // For high priority application use
|
||||
SystemPriority CommandPriority = 400 // For system tasks that access the TPM
|
||||
|
||||
commandLocalityZero uint32 = 0 // Windows currently only supports TBS_COMMAND_LOCALITY_ZERO.
|
||||
)
|
||||
|
||||
// Error is the return type of all functions in this package.
|
||||
type Error uint32
|
||||
|
||||
func (err Error) Error() string {
|
||||
if description, ok := errorDescriptions[err]; ok {
|
||||
return fmt.Sprintf("TBS Error 0x%X: %s", uint32(err), description)
|
||||
}
|
||||
return fmt.Sprintf("Unrecognized TBS Error 0x%X", uint32(err))
|
||||
}
|
||||
|
||||
func getError(err uintptr) error {
|
||||
// tbs.dll uses 0x0 as the return value for success.
|
||||
if err == 0 {
|
||||
return nil
|
||||
}
|
||||
return Error(err)
|
||||
}
|
||||
|
||||
// TBS Return Codes:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/TBS/tbs-return-codes
|
||||
const (
|
||||
ErrInternalError Error = 0x80284001
|
||||
ErrBadParameter Error = 0x80284002
|
||||
ErrInvalidOutputPointer Error = 0x80284003
|
||||
ErrInvalidContext Error = 0x80284004
|
||||
ErrInsufficientBuffer Error = 0x80284005
|
||||
ErrIOError Error = 0x80284006
|
||||
ErrInvalidContextParam Error = 0x80284007
|
||||
ErrServiceNotRunning Error = 0x80284008
|
||||
ErrTooManyTBSContexts Error = 0x80284009
|
||||
ErrTooManyResources Error = 0x8028400A
|
||||
ErrServiceStartPending Error = 0x8028400B
|
||||
ErrPPINotSupported Error = 0x8028400C
|
||||
ErrCommandCanceled Error = 0x8028400D
|
||||
ErrBufferTooLarge Error = 0x8028400E
|
||||
ErrTPMNotFound Error = 0x8028400F
|
||||
ErrServiceDisabled Error = 0x80284010
|
||||
ErrNoEventLog Error = 0x80284011
|
||||
ErrAccessDenied Error = 0x80284012
|
||||
ErrProvisioningNotAllowed Error = 0x80284013
|
||||
ErrPPIFunctionUnsupported Error = 0x80284014
|
||||
ErrOwnerauthNotFound Error = 0x80284015
|
||||
)
|
||||
|
||||
var errorDescriptions = map[Error]string{
|
||||
ErrInternalError: "An internal software error occurred.",
|
||||
ErrBadParameter: "One or more parameter values are not valid.",
|
||||
ErrInvalidOutputPointer: "A specified output pointer is bad.",
|
||||
ErrInvalidContext: "The specified context handle does not refer to a valid context.",
|
||||
ErrInsufficientBuffer: "The specified output buffer is too small.",
|
||||
ErrIOError: "An error occurred while communicating with the TPM.",
|
||||
ErrInvalidContextParam: "A context parameter that is not valid was passed when attempting to create a TBS context.",
|
||||
ErrServiceNotRunning: "The TBS service is not running and could not be started.",
|
||||
ErrTooManyTBSContexts: "A new context could not be created because there are too many open contexts.",
|
||||
ErrTooManyResources: "A new virtual resource could not be created because there are too many open virtual resources.",
|
||||
ErrServiceStartPending: "The TBS service has been started but is not yet running.",
|
||||
ErrPPINotSupported: "The physical presence interface is not supported.",
|
||||
ErrCommandCanceled: "The command was canceled.",
|
||||
ErrBufferTooLarge: "The input or output buffer is too large.",
|
||||
ErrTPMNotFound: "A compatible Trusted Platform Module (TPM) Security Device cannot be found on this computer.",
|
||||
ErrServiceDisabled: "The TBS service has been disabled.",
|
||||
ErrNoEventLog: "The TBS event log is not available.",
|
||||
ErrAccessDenied: "The caller does not have the appropriate rights to perform the requested operation.",
|
||||
ErrProvisioningNotAllowed: "The TPM provisioning action is not allowed by the specified flags.",
|
||||
ErrPPIFunctionUnsupported: "The Physical Presence Interface of this firmware does not support the requested method.",
|
||||
ErrOwnerauthNotFound: "The requested TPM OwnerAuth value was not found.",
|
||||
}
|
||||
|
||||
// Tbs.dll provides an API for making calls to the TPM:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/TBS/tpm-base-services-portal
|
||||
var (
|
||||
tbsDLL = syscall.NewLazyDLL("Tbs.dll")
|
||||
tbsGetDeviceInfo = tbsDLL.NewProc("Tbsi_GetDeviceInfo")
|
||||
tbsCreateContext = tbsDLL.NewProc("Tbsi_Context_Create")
|
||||
tbsContextClose = tbsDLL.NewProc("Tbsip_Context_Close")
|
||||
tbsSubmitCommand = tbsDLL.NewProc("Tbsip_Submit_Command")
|
||||
tbsGetTCGLog = tbsDLL.NewProc("Tbsi_Get_TCG_Log")
|
||||
)
|
||||
|
||||
// Returns the address of the beginning of a slice or 0 for a nil slice.
|
||||
func sliceAddress(s []byte) uintptr {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
return uintptr(unsafe.Pointer(&(s[0])))
|
||||
}
|
||||
|
||||
// DeviceInfo is TPM_DEVICE_INFO from tbs.h
|
||||
type DeviceInfo struct {
|
||||
StructVersion uint32
|
||||
TPMVersion Version
|
||||
TPMInterfaceType uint32
|
||||
TPMImpRevision uint32
|
||||
}
|
||||
|
||||
// GetDeviceInfo gets the DeviceInfo of the current TPM:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/tbs/nf-tbs-tbsi_getdeviceinfo
|
||||
func GetDeviceInfo() (*DeviceInfo, error) {
|
||||
info := DeviceInfo{}
|
||||
// TBS_RESULT Tbsi_GetDeviceInfo(
|
||||
// UINT32 Size,
|
||||
// PVOID Info
|
||||
// );
|
||||
if err := tbsGetDeviceInfo.Find(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, _, _ := tbsGetDeviceInfo.Call(
|
||||
unsafe.Sizeof(info),
|
||||
uintptr(unsafe.Pointer(&info)),
|
||||
)
|
||||
return &info, getError(result)
|
||||
}
|
||||
|
||||
// CreateContext creates a new TPM context:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsi_context_create
|
||||
func CreateContext(version Version, flag Flag) (Context, error) {
|
||||
var context Context
|
||||
params := struct {
|
||||
Version
|
||||
Flag
|
||||
}{version, flag}
|
||||
// TBS_RESULT Tbsi_Context_Create(
|
||||
// _In_ PCTBS_CONTEXT_PARAMS pContextParams,
|
||||
// _Out_ PTBS_HCONTEXT *phContext
|
||||
// );
|
||||
if err := tbsCreateContext.Find(); err != nil {
|
||||
return context, err
|
||||
}
|
||||
result, _, _ := tbsCreateContext.Call(
|
||||
uintptr(unsafe.Pointer(¶ms)),
|
||||
uintptr(unsafe.Pointer(&context)),
|
||||
)
|
||||
return context, getError(result)
|
||||
}
|
||||
|
||||
// Close closes an existing TPM context:
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsip_context_close
|
||||
func (context Context) Close() error {
|
||||
// TBS_RESULT Tbsip_Context_Close(
|
||||
// _In_ TBS_HCONTEXT hContext
|
||||
// );
|
||||
if err := tbsContextClose.Find(); err != nil {
|
||||
return err
|
||||
}
|
||||
result, _, _ := tbsContextClose.Call(uintptr(context))
|
||||
return getError(result)
|
||||
}
|
||||
|
||||
// SubmitCommand sends commandBuffer to the TPM, returning the number of bytes
|
||||
// written to responseBuffer. ErrInsufficientBuffer is returned if the
|
||||
// responseBuffer is too short. ErrInvalidOutputPointer is returned if the
|
||||
// responseBuffer is nil. On failure, the returned length is unspecified.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsip_submit_command
|
||||
func (context Context) SubmitCommand(
|
||||
priority CommandPriority,
|
||||
commandBuffer []byte,
|
||||
responseBuffer []byte,
|
||||
) (uint32, error) {
|
||||
responseBufferLen := uint32(len(responseBuffer))
|
||||
|
||||
// TBS_RESULT Tbsip_Submit_Command(
|
||||
// _In_ TBS_HCONTEXT hContext,
|
||||
// _In_ TBS_COMMAND_LOCALITY Locality,
|
||||
// _In_ TBS_COMMAND_PRIORITY Priority,
|
||||
// _In_ const PCBYTE *pabCommand,
|
||||
// _In_ UINT32 cbCommand,
|
||||
// _Out_ PBYTE *pabResult,
|
||||
// _Inout_ UINT32 *pcbOutput
|
||||
// );
|
||||
if err := tbsSubmitCommand.Find(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
result, _, _ := tbsSubmitCommand.Call(
|
||||
uintptr(context),
|
||||
uintptr(commandLocalityZero),
|
||||
uintptr(priority),
|
||||
sliceAddress(commandBuffer),
|
||||
uintptr(len(commandBuffer)),
|
||||
sliceAddress(responseBuffer),
|
||||
uintptr(unsafe.Pointer(&responseBufferLen)),
|
||||
)
|
||||
return responseBufferLen, getError(result)
|
||||
}
|
||||
|
||||
// GetTCGLog gets the system event log, returning the number of bytes written
|
||||
// to logBuffer. If logBuffer is nil, the size of the TCG log is returned.
|
||||
// ErrInsufficientBuffer is returned if the logBuffer is too short. On failure,
|
||||
// the returned length is unspecified.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsi_get_tcg_log
|
||||
func (context Context) GetTCGLog(logBuffer []byte) (uint32, error) {
|
||||
logBufferLen := uint32(len(logBuffer))
|
||||
|
||||
// TBS_RESULT Tbsi_Get_TCG_Log(
|
||||
// TBS_HCONTEXT hContext,
|
||||
// PBYTE pOutputBuf,
|
||||
// PUINT32 pOutputBufLen
|
||||
// );
|
||||
if err := tbsGetTCGLog.Find(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
result, _, _ := tbsGetTCGLog.Call(
|
||||
uintptr(context),
|
||||
sliceAddress(logBuffer),
|
||||
uintptr(unsafe.Pointer(&logBufferLen)),
|
||||
)
|
||||
return logBufferLen, getError(result)
|
||||
}
|
||||
Reference in New Issue
Block a user