pax_global_header 0000666 0000000 0000000 00000000064 14067646345 0014531 g ustar 00root root 0000000 0000000 52 comment=05baef61e123181de84de4de0de5100427f2fc80
go-tspi-0.3.0/ 0000775 0000000 0000000 00000000000 14067646345 0013113 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/.travis.yml 0000664 0000000 0000000 00000000212 14067646345 0015217 0 ustar 00root root 0000000 0000000 language: go
go:
- 1.10.8
- 1.11.5
arch:
- AMD64
- ppc64le
install: true
script:
- go get golang.org/x/lint/golint
- ./test
go-tspi-0.3.0/CONTRIBUTING.md 0000664 0000000 0000000 00000002115 14067646345 0015343 0 ustar 00root root 0000000 0000000 # How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
## Community Guidelines
This project follows
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
go-tspi-0.3.0/LICENSE 0000664 0000000 0000000 00000026075 14067646345 0014132 0 ustar 00root root 0000000 0000000 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.
go-tspi-0.3.0/README.md 0000664 0000000 0000000 00000003373 14067646345 0014400 0 ustar 00root root 0000000 0000000 # go-tspi - Go bindings and support code for libtspi and tpm communication
[](https://travis-ci.org/google/go-tspi)
This is a library providing a set of bindings for communication between
code written in Go and libtspi, the library responsible for providing a TPM
control interface. It consists of the following components:
## tspi
The tspi bindings for Go. These are a low-level interface intended for use by
people writing new TPM-using applications in Go. Code using these bindings must
run on the same system as the TPM. For example:
```go
// Create a new TSPI context
context, err := tspi.NewContext()
// Connect to the TPM daemon
context.connect()
// Obtain a handle to the TPM itself
tpm := context.GetTPM()
// Obtain the TPM event log
log, err := tpm.GetEventLog()
```
## attestation and verification
Helper functions for performing attestation-related tasks
```go
// Retrieve the EK certificate
ekcert, err := attestation.GetEKCert(context)
// Verify that the EK certificate is signed by a TPM vendor
err = verification.VerifyEKCert(ekcert)
if err != nil {
log.Fatal("Unable to verify EK certificate!")
}
```
## tpmd
Daemon for performing certain TPM operations at a higher level API or via a
network. Takes the listening port number as the only argument.
## tpmclient
Library for client applications communicating with tpmd. Avoids the need for
individual applications to care about TSPI context or resource lifecycles
themselves.
```go
`// Connect to the TPM daemon on localhost port 12401
client := tpmclient.New("127.0.0.1:12401")
// Extend a PCR with some data
data := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
client.Extend(15, 0x1000, data, "Test extension")`
```
go-tspi-0.3.0/attestation/ 0000775 0000000 0000000 00000000000 14067646345 0015452 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/attestation/attestation.go 0000664 0000000 0000000 00000015320 14067646345 0020341 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 attestation
import (
"errors"
"fmt"
"github.com/google/go-tspi/tspi"
"github.com/google/go-tspi/tspiconst"
)
// This is used for object use authorization
// We let it be well known because the
// additional security gained is insignificant
// compared to the inconveniences it can cause
var wellKnownSecret [20]byte
func pad(plaintext []byte, bsize int) ([]byte, error) {
if bsize >= 256 {
return nil, errors.New("bsize must be < 256")
}
pad := bsize - (len(plaintext) % bsize)
if pad == 0 {
pad = bsize
}
for i := 0; i < pad; i++ {
plaintext = append(plaintext, byte(pad))
}
return plaintext, nil
}
// AIKChallengeResponse takes the output from GenerateChallenge along with the
// encrypted AIK key blob. The TPM then decrypts the asymmetric challenge with
// its EK in order to obtain the AES key, and uses the AES key to decrypt the
// symmetrically encrypted data. It verifies that this data blob corresponds
// to the AIK it was given, and if so hands back the secret contained within
// the symmetrically encrypted data.
func AIKChallengeResponse(context *tspi.Context, aikblob []byte, asymchallenge []byte, symchallenge []byte) (secret []byte, err error) {
srk, err := context.LoadKeyByUUID(tspiconst.TSS_PS_TYPE_SYSTEM, tspi.TSS_UUID_SRK)
if err != nil {
return nil, err
}
srkpolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, err
}
srkpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnownSecret[:])
tpm := context.GetTPM()
tpmpolicy, err := context.CreatePolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, err
}
tpm.AssignPolicy(tpmpolicy)
tpmpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnownSecret[:])
aik, err := context.LoadKeyByBlob(srk, aikblob)
if err != nil {
return nil, err
}
secret, err = tpm.ActivateIdentity(aik, asymchallenge, symchallenge)
return secret, err
}
// CreateAIK asks the TPM to generate an Attestation Identity Key. It returns
// the unencrypted public half of the AIK along with an encrypted blob
// containing both halves of the key, and any error.
func CreateAIK(context *tspi.Context) ([]byte, []byte, error) {
n := make([]byte, 2048/8)
for i := 0; i < 2048/8; i++ {
n[i] = 0xff
}
srk, err := context.LoadKeyByUUID(tspiconst.TSS_PS_TYPE_SYSTEM, tspi.TSS_UUID_SRK)
if err != nil {
return nil, nil, err
}
keypolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, nil, err
}
err = keypolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnownSecret[:])
if err != nil {
return nil, nil, err
}
tpm := context.GetTPM()
tpmpolicy, err := tpm.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, nil, err
}
err = tpm.AssignPolicy(tpmpolicy)
if err != nil {
return nil, nil, err
}
err = tpmpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnownSecret[:])
if err != nil {
return nil, nil, err
}
pcakey, err := context.CreateKey(tspiconst.TSS_KEY_TYPE_LEGACY | tspiconst.TSS_KEY_SIZE_2048)
if err != nil {
return nil, nil, err
}
err = pcakey.SetModulus(n)
if err != nil {
return nil, nil, err
}
aik, err := context.CreateKey(tspiconst.TSS_KEY_TYPE_IDENTITY | tspiconst.TSS_KEY_SIZE_2048)
if err != nil {
return nil, nil, err
}
_, err = tpm.CollateIdentityRequest(srk, pcakey, aik)
if err != nil {
return nil, nil, err
}
pubkey, err := aik.GetPubKeyBlob()
if err != nil {
return nil, nil, err
}
blob, err := aik.GetKeyBlob()
if err != nil {
return nil, nil, err
}
_, err = aik.GetModulus()
return pubkey, blob, nil
}
// GetQuote consumes a nonce and the aik blob and returns the quote,
// a signature, and any error
func GetQuote(context *tspi.Context, aikblob, nonce []byte) ([]byte, []byte, error) {
srk, err := context.LoadKeyByUUID(tspiconst.TSS_PS_TYPE_SYSTEM, tspi.TSS_UUID_SRK)
if err != nil {
return nil, nil, fmt.Errorf("LoadKeyByUUID failed: %v", err)
}
srkpolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, nil, fmt.Errorf("GetPolicy failed: %v", err)
}
srkpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnownSecret[:])
tpm := context.GetTPM()
aik, err := context.LoadKeyByBlob(srk, aikblob)
if err != nil {
return nil, nil, fmt.Errorf("LoadKeyByBlob failed: %v", err)
}
pcrs, err := context.CreatePCRs(tspiconst.TSS_PCRS_STRUCT_DEFAULT)
if err != nil {
return nil, nil, fmt.Errorf("failed to get a reference to PCRs: %v", err)
}
// GetQuote will only quote the PCR values that are selected by SetPCRs()
// We want all the PCR values so we pass a slice of 0 through 23
selectedPCRs := make([]int, 24)
for i := 0; i < 24; i++ {
selectedPCRs[i] = i
}
if err = pcrs.SetPCRs(selectedPCRs); err != nil {
return nil, nil, fmt.Errorf("failed to set the PCR bitmap %v", err)
}
return tpm.GetQuote(aik, pcrs, nonce)
}
// GetEKCert reads the Endorsement Key certificate from the TPM's NVRAM and
// returns it, along with any error generated.
func GetEKCert(context *tspi.Context) (ekcert []byte, err error) {
tpm := context.GetTPM()
nv, err := context.CreateNV()
if err != nil {
return nil, err
}
policy, err := tpm.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, err
}
policy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnownSecret[:])
nv.SetIndex(0x1000f000)
nv.AssignPolicy(policy)
data, err := nv.ReadValue(0, 5)
if err != nil {
return nil, err
}
tag := (uint)((uint)(data[0])<<8 | (uint)(data[1]))
if tag != 0x1001 {
return nil, fmt.Errorf("invalid tag: %x", tag)
}
if data[2] != 0 {
return nil, fmt.Errorf("invalid certificate")
}
ekbuflen := (uint)(uint(data[3])<<8 | (uint)(data[4]))
offset := (uint)(5)
data, err = nv.ReadValue(offset, 2)
tag = (uint)((uint)(data[0])<<8 | (uint)(data[1]))
if tag == 0x1002 {
offset += 2
ekbuflen -= 2
} else if data[0] != 0x30 {
return nil, fmt.Errorf("invalid header: %x", tag)
}
ekoffset := (uint)(0)
var ekbuf []byte
for ekoffset < ekbuflen {
length := (uint)(ekbuflen - ekoffset)
if length > 128 {
length = 128
}
data, err = nv.ReadValue(offset, length)
if err != nil {
return nil, err
}
ekbuf = append(ekbuf, data...)
offset += length
ekoffset += length
}
return ekbuf, nil
}
go-tspi-0.3.0/go.mod 0000664 0000000 0000000 00000000262 14067646345 0014221 0 ustar 00root root 0000000 0000000 module github.com/google/go-tspi
go 1.12
require (
github.com/google/certificate-transparency-go v1.0.21
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 // indirect
)
go-tspi-0.3.0/go.sum 0000664 0000000 0000000 00000001023 14067646345 0014242 0 ustar 00root root 0000000 0000000 github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
go-tspi-0.3.0/test 0000775 0000000 0000000 00000001723 14067646345 0014023 0 ustar 00root root 0000000 0000000 #!/bin/bash -e
#
# source ./build
TESTABLE=""
FORMATTABLE="$TESTABLE attestation tpmd tspi verification tpmclient tpmown tspiconst"
# user has not provided PKG override
if [ -z "$PKG" ]; then
TEST=$TESTABLE
FMT=$FORMATTABLE
# user has provided PKG override
else
# strip out slashes and dots from PKG=./foo/
TEST=${PKG//\//}
TEST=${TEST//./}
# only run gofmt on packages provided by user
FMT="$TEST"
fi
# split TEST into an array and prepend REPO_PATH to each local package
split=(${TEST// / })
TEST=${split[@]/#/${REPO_PATH}/}
# TODO: add tests..
# echo "Running tests..."
# go test ${COVER} $@ ${TEST}
echo "Checking gofmt..."
fmtRes=$(gofmt -l $FMT)
if [ -n "${fmtRes}" ]; then
echo -e "gofmt checking failed:\n${fmtRes}"
exit 255
fi
echo "Checking golint..."
# tpmclient and tspiconst declare C style constants and don't pass golint. For
# now ignore them.
golint -set_exit_status \
./attestation \
./tpmd \
./tpmown \
./verification
echo "Success"
go-tspi-0.3.0/tpmclient/ 0000775 0000000 0000000 00000000000 14067646345 0015112 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/tpmclient/tpmclient.go 0000664 0000000 0000000 00000020717 14067646345 0017447 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tpmclient
import (
"bytes"
"crypto/rand"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"time"
"github.com/google/go-tspi/tspiconst"
"github.com/google/go-tspi/verification"
)
// TPMClient represents a connection to a system running a daemon providing
// access to TPM functionality
type TPMClient struct {
host string
timeout time.Duration
}
const (
GetEKCertURL = "/v1/getEkcert"
ExtendURL = "/v1/extend"
QuoteURL = "/v1/quote"
GenerateAikURL = "/v1/generateAik"
GenerateKeyURL = "/v1/generateKey"
AikChallengeURL = "/v1/aikChallenge"
)
func (client *TPMClient) get(endpoint string) (*http.Response, error) {
url := fmt.Sprintf("http://%s%s", client.host, endpoint)
httpClient := &http.Client{
Timeout: client.timeout,
}
resp, err := httpClient.Get(url)
return resp, err
}
func (client *TPMClient) post(endpoint string, data io.Reader) (*http.Response, error) {
url := fmt.Sprintf("http://%s%s", client.host, endpoint)
httpClient := &http.Client{
Timeout: client.timeout,
}
resp, err := httpClient.Post(url, "application/json", data)
return resp, err
}
type EkcertResponse struct {
EKCert []byte
}
// GetEKCert obtains the Endorsement Key certificate from the client TPM. This
// is an X509 certificate containing the public half of the Endorsement Key
// and a signature chain chaining back to a vendor-issued signing certificate.
func (client *TPMClient) GetEKCert() (ekcert []byte, err error) {
var ekcertData EkcertResponse
ekresp, err := client.get(GetEKCertURL)
if err != nil {
return nil, fmt.Errorf("Can't obtain ekcert: %s", err)
}
defer ekresp.Body.Close()
body, err := ioutil.ReadAll(ekresp.Body)
if err != nil {
return nil, fmt.Errorf("Can't read ekcert response: %s", err)
}
err = json.Unmarshal(body, &ekcertData)
if err != nil {
return nil, fmt.Errorf("Can't parse ekcert response: %s", err)
}
return ekcertData.EKCert, nil
}
type AikResponse struct {
AIKBlob []byte
AIKPub []byte
}
// GenerateAIK requests that the TPM generate a new Attestation Identity Key.
// It returns an unencrypted copy of the public half of the AIK, along with
// a TSPI key blob encrypted by the TPM.
func (client *TPMClient) GenerateAIK() (aikpub []byte, aikblob []byte, err error) {
var aikData AikResponse
aikresp, err := client.post(GenerateAikURL, nil)
if err != nil {
return nil, nil, fmt.Errorf("Can't generate AIK: %s", err)
}
defer aikresp.Body.Close()
body, err := ioutil.ReadAll(aikresp.Body)
if err != nil {
return nil, nil, fmt.Errorf("Can't read AIK response: %s", err)
}
err = json.Unmarshal(body, &aikData)
if err != nil {
return nil, nil, fmt.Errorf("Can't parse AIK response: %s (%s)", err, body)
}
aikpub = aikData.AIKPub
aikblob = aikData.AIKBlob
return aikpub, aikblob, nil
}
type KeyData struct {
KeyFlags int
}
type KeyResponse struct {
KeyBlob []byte
KeyPub []byte
}
// GenerateKey requests that the TPM generate a new keypair
func (client *TPMClient) GenerateKey(flags int) (keypub []byte, keyblob []byte, err error) {
var keyData KeyData
var keyResponse KeyResponse
keyData.KeyFlags = flags
request, err := json.Marshal(keyData)
if err != nil {
return nil, nil, fmt.Errorf("Can't construct request JSON: %s", err)
}
keyresp, err := client.post(GenerateKeyURL, bytes.NewBuffer(request))
if err != nil {
return nil, nil, fmt.Errorf("Can't generate key: %s", err)
}
defer keyresp.Body.Close()
body, err := ioutil.ReadAll(keyresp.Body)
if err != nil {
return nil, nil, fmt.Errorf("Can't read key response: %s", err)
}
err = json.Unmarshal(body, &keyResponse)
if err != nil {
return nil, nil, fmt.Errorf("Can't parse key response: %s (%s)", err, body)
}
keypub = keyResponse.KeyPub
keyblob = keyResponse.KeyBlob
return keypub, keyblob, nil
}
type ChallengeData struct {
AIK []byte
Asymenc []byte
Symenc []byte
}
type ChallengeResponse struct {
Response []byte
}
// ValidateAIK challenges the TPM to validate an AIK by using the provided
// key blob to decrypt a secret encrypted with the public half of the
// AIK. This will only be possible if the TPM is able to decrypt the
// encrypted key blob. The AIK is used to decrypt asymenc, which then
// provides the AES key used to encrypt symenc. Decrypting symenc provides
// the original secret, which is then returned.
func (client *TPMClient) ValidateAIK(aikblob []byte, asymenc []byte, symenc []byte) (secret []byte, err error) {
var challenge ChallengeData
var response ChallengeResponse
challenge.AIK = aikblob
challenge.Asymenc = asymenc
challenge.Symenc = symenc
request, err := json.Marshal(challenge)
if err != nil {
return nil, fmt.Errorf("Can't construct challenge JSON: %s", err)
}
chalresp, err := client.post(AikChallengeURL, bytes.NewBuffer(request))
if err != nil {
return nil, fmt.Errorf("Can't perform AIK challenge: %s", err)
}
defer chalresp.Body.Close()
body, err := ioutil.ReadAll(chalresp.Body)
if err != nil {
return nil, fmt.Errorf("Can't read AIK challenge response: %s", err)
}
err = json.Unmarshal(body, &response)
if err != nil {
return nil, fmt.Errorf("Can't parse AIK challenge response: %s", err)
}
return response.Response, nil
}
type ExtendInput struct {
Pcr int
Eventtype int
Data []byte
Event string
}
// Extend extends a TPM PCR with the provided data. If event is nil, data must
// be pre-hashed with SHA1 and will be used to extend the PCR directly. If
// event is not nil, data and event will be hashed to generate the extension
// value. Event will then be stored in the TPM event log.
func (client *TPMClient) Extend(pcr int, eventtype int, data []byte, event string) error {
var extendData ExtendInput
extendData.Pcr = pcr
extendData.Eventtype = eventtype
extendData.Data = data
extendData.Event = event
request, err := json.Marshal(extendData)
if err != nil {
return fmt.Errorf("Can't construct extension JSON: %s", err)
}
chalresp, err := client.post(ExtendURL, bytes.NewBuffer(request))
if err != nil {
return fmt.Errorf("Can't perform PCR extension: %s", err)
}
defer chalresp.Body.Close()
return nil
}
type QuoteData struct {
AIK []byte
PCRs []int
Nonce []byte
}
type QuoteResponse struct {
Data []byte
Validation []byte
PCRValues [][]byte
Events []tspiconst.Log
}
// GetQuote obtains a PCR quote from the TPM. It takes the aikpub Tspi Key, the
// encrypted AIK blob and a list of PCRs as arguments. The response will
// contain an array of PCR values, an array of log entries and any error.
func (client *TPMClient) GetQuote(aikpub []byte, aikblob []byte, pcrs []int) (pcrvals [][]byte, log []tspiconst.Log, err error) {
var quoteRequest QuoteData
var response QuoteResponse
nonce := make([]byte, 20)
_, err = rand.Read(nonce)
if err != nil {
return nil, nil, fmt.Errorf("Unable to generate nonce: %s", err)
}
quoteRequest.AIK = aikblob
quoteRequest.PCRs = pcrs
quoteRequest.Nonce = nonce
request, err := json.Marshal(quoteRequest)
if err != nil {
return nil, nil, fmt.Errorf("Can't construct quote request JSON: %s", err)
}
chalresp, err := client.post(QuoteURL, bytes.NewBuffer(request))
if err != nil {
return nil, nil, fmt.Errorf("Can't perform obtain quote: %s", err)
}
defer chalresp.Body.Close()
body, err := ioutil.ReadAll(chalresp.Body)
if err != nil {
return nil, nil, fmt.Errorf("Can't read quote response: %s", err)
}
err = json.Unmarshal(body, &response)
if err != nil {
return nil, nil, fmt.Errorf("Can't parse quote response: %s", err)
}
aikmod := aikpub[28:]
err = verification.QuoteVerify(response.Data, response.Validation, aikmod, response.PCRValues, nonce)
if err != nil {
return nil, nil, fmt.Errorf("Can't verify quote: %s", err)
}
return response.PCRValues, response.Events, nil
}
// New returns a TPMClient structure configured to connect to the provided
// host with the provided timeout.
func New(host string, timeout time.Duration) *TPMClient {
return &TPMClient{
host: host,
timeout: timeout,
}
}
go-tspi-0.3.0/tpmd/ 0000775 0000000 0000000 00000000000 14067646345 0014057 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/tpmd/tpmd.go 0000664 0000000 0000000 00000021727 14067646345 0015363 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"sync"
"github.com/google/go-tspi/attestation"
"github.com/google/go-tspi/tpmclient"
"github.com/google/go-tspi/tspi"
"github.com/google/go-tspi/tspiconst"
)
var wellKnown [20]byte
var pcrmutex sync.RWMutex
func setupContext() (*tspi.Context, *tspi.TPM, error) {
context, err := tspi.NewContext()
if err != nil {
return nil, nil, err
}
context.Connect()
tpm := context.GetTPM()
tpmpolicy, err := context.CreatePolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, nil, err
}
tpm.AssignPolicy(tpmpolicy)
tpmpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
return context, tpm, nil
}
func cleanupContext(context *tspi.Context) {
context.Close()
}
func loadSRK(context *tspi.Context) (*tspi.Key, error) {
srk, err := context.LoadKeyByUUID(tspiconst.TSS_PS_TYPE_SYSTEM, tspi.TSS_UUID_SRK)
if err != nil {
return nil, err
}
srkpolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
return nil, err
}
srkpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
return srk, nil
}
func getEkcert(rw http.ResponseWriter, request *http.Request) {
var output tpmclient.EkcertResponse
context, _, err := setupContext()
defer cleanupContext(context)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
if request.Method != "GET" {
rw.WriteHeader(http.StatusBadRequest)
return
}
ekcert, err := attestation.GetEKCert(context)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte(err.Error()))
return
}
output.EKCert = ekcert
jsonresponse, err := json.Marshal(output)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte(err.Error()))
return
}
rw.Write(jsonresponse)
}
func generateAik(rw http.ResponseWriter, request *http.Request) {
var output tpmclient.AikResponse
context, _, err := setupContext()
defer cleanupContext(context)
if request.Method != "POST" {
rw.WriteHeader(http.StatusBadRequest)
return
}
aikpub, aikblob, err := attestation.CreateAIK(context)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
output.AIKPub = aikpub
output.AIKBlob = aikblob
jsonresponse, err := json.Marshal(output)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
rw.Write(jsonresponse)
}
func generateKey(rw http.ResponseWriter, request *http.Request) {
var input tpmclient.KeyData
var output tpmclient.KeyResponse
body, err := ioutil.ReadAll(request.Body)
if request.Method != "POST" {
rw.WriteHeader(http.StatusBadRequest)
return
}
err = json.Unmarshal(body, &input)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte(err.Error()))
return
}
context, _, err := setupContext()
defer cleanupContext(context)
srk, err := loadSRK(context)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
key, err := context.CreateKey(input.KeyFlags)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
err = key.GenerateKey(srk)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
keypub, err := key.GetPubKeyBlob()
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
keyblob, err := key.GetKeyBlob()
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
output.KeyPub = keypub
output.KeyBlob = keyblob
jsonresponse, err := json.Marshal(output)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
rw.Write(jsonresponse)
}
func aikChallenge(rw http.ResponseWriter, request *http.Request) {
body, err := ioutil.ReadAll(request.Body)
var input tpmclient.ChallengeData
var output tpmclient.ChallengeResponse
context, _, err := setupContext()
defer cleanupContext(context)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
if request.Method != "POST" {
rw.WriteHeader(http.StatusBadRequest)
return
}
err = json.Unmarshal(body, &input)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte(err.Error()))
return
}
response, err := attestation.AIKChallengeResponse(context, input.AIK, input.Asymenc, input.Symenc)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
output.Response = response
jsonresponse, err := json.Marshal(output)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
rw.Write(jsonresponse)
}
func quote(rw http.ResponseWriter, request *http.Request) {
body, err := ioutil.ReadAll(request.Body)
var input tpmclient.QuoteData
var output tpmclient.QuoteResponse
context, tpm, err := setupContext()
defer cleanupContext(context)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
if request.Method != "POST" {
rw.WriteHeader(http.StatusBadRequest)
return
}
err = json.Unmarshal(body, &input)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte(err.Error()))
return
}
pcrs, err := context.CreatePCRs(tspiconst.TSS_PCRS_STRUCT_INFO)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
err = pcrs.SetPCRs(input.PCRs)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
srk, err := context.LoadKeyByUUID(tspiconst.TSS_PS_TYPE_SYSTEM, tspi.TSS_UUID_SRK)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
srkpolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
srkpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
aik, err := context.LoadKeyByBlob(srk, input.AIK)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
pcrmutex.Lock()
data, validation, err := tpm.GetQuote(aik, pcrs, input.Nonce)
if err != nil {
pcrmutex.Unlock()
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
pcrvalues, err := pcrs.GetPCRValues()
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
pcrmutex.Unlock()
return
}
log, err := tpm.GetEventLog()
pcrmutex.Unlock()
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
output.Data = data
output.Validation = validation
output.PCRValues = pcrvalues
output.Events = log
jsonoutput, err := json.Marshal(output)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
rw.Write(jsonoutput)
}
func extend(rw http.ResponseWriter, request *http.Request) {
body, err := ioutil.ReadAll(request.Body)
var data tpmclient.ExtendInput
context, tpm, err := setupContext()
defer cleanupContext(context)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
if request.Method != "POST" {
rw.WriteHeader(http.StatusBadRequest)
return
}
err = json.Unmarshal(body, &data)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte(err.Error()))
return
}
pcrmutex.Lock()
err = tpm.ExtendPCR(data.Pcr, data.Data, data.Eventtype, []byte(data.Event))
pcrmutex.Unlock()
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write([]byte(err.Error()))
return
}
rw.Write([]byte("OK"))
}
func main() {
if len(os.Args) < 2 {
fmt.Printf("Usage: %s port\n", os.Args[0])
return
}
socket := fmt.Sprintf(":%s", os.Args[1])
http.HandleFunc(tpmclient.ExtendURL, extend)
http.HandleFunc(tpmclient.QuoteURL, quote)
http.HandleFunc(tpmclient.GetEKCertURL, getEkcert)
http.HandleFunc(tpmclient.GenerateAikURL, generateAik)
http.HandleFunc(tpmclient.GenerateKeyURL, generateKey)
http.HandleFunc(tpmclient.AikChallengeURL, aikChallenge)
err := http.ListenAndServe(socket, nil)
if err != nil {
fmt.Printf("Unable to listen - %s\n", err)
}
}
go-tspi-0.3.0/tpmown/ 0000775 0000000 0000000 00000000000 14067646345 0014437 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/tpmown/tpmown.go 0000664 0000000 0000000 00000003402 14067646345 0016311 0 ustar 00root root 0000000 0000000 package main
import (
"bytes"
"io/ioutil"
"log"
"os"
"os/exec"
"github.com/google/go-tspi/tspi"
"github.com/google/go-tspi/tspiconst"
)
var wellKnown [20]byte
func main() {
enable := []byte("6")
activate := []byte("3")
val, err := ioutil.ReadFile("/sys/class/tpm/tpm0/device/enabled")
if os.IsNotExist(err) {
log.Fatalf("System has no tpm")
}
if bytes.Equal(val, []byte("0\n")) {
ioutil.WriteFile("/sys/class/tpm/tpm0/device/ppi/request", enable, 0664)
exec.Command("reboot", "").Run()
}
val, err = ioutil.ReadFile("/sys/class/tpm/tpm0/device/active")
if bytes.Equal(val, []byte("0\n")) {
ioutil.WriteFile("/sys/class/tpm/tpm0/device/ppi/request", activate, 0664)
exec.Command("reboot", "").Run()
}
val, err = ioutil.ReadFile("/sys/class/tpm/tpm0/device/owned")
if bytes.Equal(val, []byte("0\n")) {
context, err := tspi.NewContext()
if err != nil {
log.Fatalf("Unable to create TSS context")
}
context.Connect()
tpm := context.GetTPM()
tpmpolicy, err := tpm.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
log.Fatalf("Unable to obtain TPM policy")
}
err = tpmpolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
if err != nil {
log.Fatalf("Unable to set TPM policy")
}
srk, err := context.CreateKey(tspiconst.TSS_KEY_TSP_SRK | tspiconst.TSS_KEY_AUTHORIZATION)
if err != nil {
log.Fatalf("Unable to create SRK")
}
keypolicy, err := srk.GetPolicy(tspiconst.TSS_POLICY_USAGE)
if err != nil {
log.Fatalf("Unable to obtain SRK policy")
}
err = keypolicy.SetSecret(tspiconst.TSS_SECRET_MODE_SHA1, wellKnown[:])
if err != nil {
log.Fatalf("Unable to set SRK policy")
}
err = tpm.TakeOwnership(srk)
if err != nil {
log.Fatalf("Unable to take ownership of TPM: %v", err)
}
}
}
go-tspi-0.3.0/tspi/ 0000775 0000000 0000000 00000000000 14067646345 0014072 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/tspi/context.go 0000664 0000000 0000000 00000012740 14067646345 0016111 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
import (
"crypto"
"unsafe"
)
// Context is a TSS context
type Context struct {
context C.TSS_HCONTEXT
tpm TPM
}
// NewContext returns a TSS daemon context
func NewContext() (*Context, error) {
context := new(Context)
err := tspiError(C.Tspi_Context_Create(&context.context))
return context, err
}
// Connect opens a connection between the context and the TSS daemon. It
// returns an error on failure.
func (context *Context) Connect() error {
var tpmhandle C.TSS_HTPM
err := tspiError(C.Tspi_Context_Connect(context.context, nil))
if err != nil {
return err
}
C.Tspi_Context_GetTpmObject(context.context, &tpmhandle)
context.tpm = TPM{handle: tpmhandle, context: context.context}
return nil
}
// Close closes the connection between the context and the TSS daemon. It
// returns an error on failure.
func (context *Context) Close() error {
err := tspiError(C.Tspi_Context_Close(context.context))
return err
}
// CreateNV creates a TSS object referring to a TPM NVRAM area. It returns a
// reference to the object and any error.
func (context *Context) CreateNV() (*NV, error) {
var handle C.TSS_HNVSTORE
err := tspiError(C.Tspi_Context_CreateObject(context.context, C.TSS_OBJECT_TYPE_NV, 0, (*C.TSS_HOBJECT)(&handle)))
return &NV{handle: handle, context: context.context}, err
}
// CreateKey creates a TSS object referring to a TPM key. It returns a
// reference to the object and any error.
func (context *Context) CreateKey(flags int) (*Key, error) {
var handle C.TSS_HKEY
err := tspiError(C.Tspi_Context_CreateObject(context.context, C.TSS_OBJECT_TYPE_RSAKEY, (C.TSS_FLAG)(flags), (*C.TSS_HOBJECT)(&handle)))
return &Key{handle: handle, context: context.context}, err
}
// LoadKeyByUUID loads the key referenced by UUID. The storetype argument
// indicates whether the key should be obtained from the system or user
// stores. It returns a reference to the key and any error.
func (context *Context) LoadKeyByUUID(storetype int, uuid C.TSS_UUID) (*Key, error) {
var handle C.TSS_HKEY
err := tspiError(C.Tspi_Context_LoadKeyByUUID(context.context, (C.TSS_FLAG)(storetype), uuid, &handle))
return &Key{handle: handle, context: context.context}, err
}
// LoadKeyByBlob takes an encrypted key blob and reads it into the TPM. It
// takes a reference to the parent key and the key blob, and returns a
// reference to the key and any error.
func (context *Context) LoadKeyByBlob(parent *Key, blob []byte) (*Key, error) {
var handle C.TSS_HKEY
err := tspiError(C.Tspi_Context_LoadKeyByBlob(context.context, parent.handle, (C.UINT32)(len(blob)), (*C.BYTE)(unsafe.Pointer(&blob[0])), &handle))
return &Key{handle: handle, context: context.context}, err
}
// GetTPM returns a reference to the TPM associated with this context
func (context *Context) GetTPM() *TPM {
return &context.tpm
}
// CreatePolicy creates an object referring to a TSS policy. It returns a
// reference to the object plus any error.
func (context *Context) CreatePolicy(flags int) (*Policy, error) {
var handle C.TSS_HPOLICY
err := tspiError(C.Tspi_Context_CreateObject(context.context, C.TSS_OBJECT_TYPE_POLICY, (C.TSS_FLAG)(flags), (*C.TSS_HOBJECT)(&handle)))
return &Policy{handle: handle, context: context.context}, err
}
// CreatePCRs creates an object referring to a TSS PCR composite. It returns
// a reference to the object plus any error.
func (context *Context) CreatePCRs(flags int) (*PCRs, error) {
var handle C.TSS_HPCRS
err := tspiError(C.Tspi_Context_CreateObject(context.context, C.TSS_OBJECT_TYPE_PCRS, (C.TSS_FLAG)(flags), (*C.TSS_HOBJECT)(&handle)))
return &PCRs{handle: handle, context: context.context}, err
}
// CreateHash creates a Hash object for the given hash algorithm. If using an algorithm other than crypto.SHA1 and
// if you are signing with this hash then make sure the key is created with signing algorithm TSS_SS_RSASSAPKCS1V15_DER.
func (context *Context) CreateHash(hash crypto.Hash) (*Hash, error) {
var hashAlg C.TSS_FLAG
if hash == crypto.SHA1 {
hashAlg = C.TSS_HASH_SHA1
} else {
hashAlg = C.TSS_HASH_OTHER
}
var handle C.TSS_HHASH
err := tspiError(C.Tspi_Context_CreateObject(context.context, C.TSS_OBJECT_TYPE_HASH, hashAlg, (*C.TSS_HOBJECT)(&handle)))
if err != nil {
return nil, err
}
return &Hash{
context: context.context,
handle: handle,
hashAlg: hash,
}, nil
}
// GetCapability reads the requested capability and subcapability from the TPM.
// A list of capabilities and subcapabilities can be found under tspiconst/tpsiconst.
// For usage information see Section 21.1 of the TPM1.2 main specification-part2.
func (context *Context) GetCapability(capa int, subcaplen uint, subcap uint8) ([]byte, error) {
var resplen C.uint
var resp *C.BYTE
err := tspiError(C.Tspi_TPM_GetCapability(context.tpm.handle, (C.TSS_FLAG)(capa), (C.uint)(subcaplen), (*C.BYTE)(unsafe.Pointer(&subcap)), &resplen, &resp))
return C.GoBytes(unsafe.Pointer(resp), C.int(resplen)), err
}
go-tspi-0.3.0/tspi/hash.go 0000664 0000000 0000000 00000006533 14067646345 0015353 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
import (
"crypto"
"errors"
"unsafe"
)
// Hash is a TSS hash
type Hash struct {
handle C.TSS_HHASH
context C.TSS_HCONTEXT
hashAlg crypto.Hash
}
// Update updates a TSS hash with the data provided. It returns an error on
// failure.
func (hash *Hash) Update(data []byte) error {
err := tspiError(C.Tspi_Hash_UpdateHashValue(hash.handle, (C.UINT32)(len(data)), (*C.BYTE)(&data[0])))
return err
}
// Verify checks whether a hash matches the signature signed with the
// provided key. It returns an error on failure.
func (hash *Hash) Verify(key *Key, signature []byte) error {
err := tspiError(C.Tspi_Hash_VerifySignature(hash.handle, key.handle, (C.UINT32)(len(signature)), (*C.BYTE)(&signature[0])))
return err
}
// https://golang.org/src/crypto/rsa/pkcs1v15.go#L204
var hashPrefixes = map[crypto.Hash][]byte{
crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
}
// SetValue sets the value of the hash to the given bytes
func (hash *Hash) SetValue(hashed []byte) error {
var data []byte
if hash.hashAlg == crypto.SHA1 {
data = hashed
} else {
prefix, ok := hashPrefixes[hash.hashAlg]
if !ok {
return errors.New("unsupported hash algorithm")
}
data = append(prefix, hashed...)
}
return tspiError(C.Tspi_Hash_SetHashValue(hash.handle, (C.UINT32)(len(data)), (*C.BYTE)(&data[0])))
}
// Sign uses the provided key to create a signature.
func (hash *Hash) Sign(key *Key) ([]byte, error) {
var dataLen C.UINT32
var cData *C.BYTE
err := tspiError(C.Tspi_Hash_Sign(hash.handle, key.handle, &dataLen, &cData))
data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
C.Tspi_Context_FreeMemory(hash.context, cData)
if err != nil {
return nil, err
}
return data, nil
}
// Close closes the Hash object.
func (hash *Hash) Close() error {
err := tspiError(C.Tspi_Context_CloseObject(hash.context, hash.handle))
return err
}
go-tspi-0.3.0/tspi/key.go 0000664 0000000 0000000 00000022347 14067646345 0015221 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
import (
"crypto/rsa"
"crypto/sha1"
"errors"
"math/big"
"unsafe"
)
// ModulusFromBlob provides the modulus of a provided TSS key blob
func ModulusFromBlob(blob []byte) []byte {
return blob[28:]
}
// Key is a TSS key
type Key struct {
handle C.TSS_HKEY
context C.TSS_HCONTEXT
}
// GetPolicy returns the policy associated with the key
func (key *Key) GetPolicy(poltype int) (*Policy, error) {
var policyHandle C.TSS_HPOLICY
err := tspiError(C.Tspi_GetPolicyObject((C.TSS_HOBJECT)(key.handle), (C.TSS_FLAG)(poltype), &policyHandle))
return &Policy{handle: policyHandle, context: key.context}, err
}
// SetModulus sets the modulus of a public key to the provided value
func (key *Key) SetModulus(n []byte) error {
err := tspiError(C.Tspi_SetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, (C.UINT32)(len(n)), (*C.BYTE)(unsafe.Pointer(&n[0]))))
return err
}
// GetExponent returns the exponent of the public key
func (key *Key) GetExponent() (uint32, error) {
var dataLen C.UINT32
var cData *C.BYTE
err := tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT, &dataLen, &cData))
data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
C.Tspi_Context_FreeMemory(key.context, cData)
if err != nil {
return 0, err
}
if len(data) > 4 {
return 0, errors.New("Exponent doesn't fit in int")
}
var exponent uint32
for _, b := range data {
exponent = (exponent << 8) + uint32(b)
}
return exponent, nil
}
// GetPublicKey returns a go-native *rsa.PublicKey instance of this key's public key
func (key *Key) GetPublicKey() (*rsa.PublicKey, error) {
modulus, err := key.GetModulus()
if err != nil {
return nil, err
}
exponent, err := key.GetExponent()
if err != nil {
return nil, err
}
pk := &rsa.PublicKey{
N: new(big.Int).SetBytes(modulus),
E: int(exponent),
}
return pk, nil
}
// GetModulus returns the modulus of the public key
func (key *Key) GetModulus() (modulus []byte, err error) {
var dataLen C.UINT32
var cData *C.BYTE
err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &dataLen, &cData))
data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
C.Tspi_Context_FreeMemory(key.context, cData)
return data, err
}
// GetPubKeyBlob returns the public half of the key in TPM blob format
func (key *Key) GetPubKeyBlob() (pubkey []byte, err error) {
var dataLen C.UINT32
var cData *C.BYTE
err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_BLOB, C.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &dataLen, &cData))
data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
C.Tspi_Context_FreeMemory(key.context, cData)
return data, err
}
// GetKeyBlob returns an encrypted blob containing the public and private
// halves of the key
func (key *Key) GetKeyBlob() ([]byte, error) {
var dataLen C.UINT32
var cData *C.BYTE
err := tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_BLOB, C.TSS_TSPATTRIB_KEYBLOB_BLOB, &dataLen, &cData))
data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
C.Tspi_Context_FreeMemory(key.context, cData)
return data, err
}
// Bind encrypts some data using the TPM and returns it.
func (key *Key) Bind(data []byte) ([]byte, error) {
var encdata C.TSS_HENCDATA
var dataLen C.UINT32
var cData *C.BYTE
err := tspiError(C.Tspi_Context_CreateObject(key.context, C.TSS_OBJECT_TYPE_ENCDATA, C.TSS_ENCDATA_BIND, (*C.TSS_HOBJECT)(&encdata)))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_Data_Bind(encdata, key.handle, (C.UINT32)(len(data)), (*C.BYTE)(&data[0])))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(encdata), C.TSS_TSPATTRIB_ENCDATA_BLOB, C.TSS_TSPATTRIB_ENCDATABLOB_BLOB, &dataLen, &cData))
if err != nil {
return nil, err
}
blob := C.GoBytes(unsafe.Pointer(cData), (C.int(dataLen)))
C.Tspi_Context_FreeMemory(key.context, cData)
return blob, nil
}
// Unbind decrypts data previously encrypted with this key
func (key *Key) Unbind(data []byte) ([]byte, error) {
var encdata C.TSS_HENCDATA
var dataLen C.UINT32
var cData *C.BYTE
err := tspiError(C.Tspi_Context_CreateObject(key.context, C.TSS_OBJECT_TYPE_ENCDATA, C.TSS_ENCDATA_BIND, (*C.TSS_HOBJECT)(&encdata)))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_SetAttribData((C.TSS_HOBJECT)(encdata), C.TSS_TSPATTRIB_ENCDATA_BLOB, C.TSS_TSPATTRIB_ENCDATABLOB_BLOB, (C.UINT32)(len(data)), (*C.BYTE)(unsafe.Pointer(&data[0]))))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_Data_Unbind(encdata, key.handle, &dataLen, &cData))
if err != nil {
return nil, err
}
blob := C.GoBytes(unsafe.Pointer(cData), (C.int(dataLen)))
C.Tspi_Context_FreeMemory(key.context, cData)
return blob, nil
}
// Seal encrypts the data using the TPM such that it can only be decrypted
// when the TPM's PCR values match the values set on the provided PCRs
// object. If pcrs is nil, the data will be sealed to the TPM but may be
// decrypted regardless of platform state.
func (key *Key) Seal(data []byte, pcrs *PCRs) ([]byte, error) {
var encdata C.TSS_HENCDATA
var dataLen C.UINT32
var cData *C.BYTE
var pcrhandle C.TSS_HPCRS
if pcrs != nil {
pcrhandle = pcrs.handle
}
err := tspiError(C.Tspi_Context_CreateObject(key.context, C.TSS_OBJECT_TYPE_ENCDATA, C.TSS_ENCDATA_SEAL, (*C.TSS_HOBJECT)(&encdata)))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_Data_Seal(encdata, key.handle, (C.UINT32)(len(data)), (*C.BYTE)(&data[0]), pcrhandle))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(encdata), C.TSS_TSPATTRIB_ENCDATA_BLOB, C.TSS_TSPATTRIB_ENCDATABLOB_BLOB, &dataLen, &cData))
if err != nil {
return nil, err
}
blob := C.GoBytes(unsafe.Pointer(cData), (C.int(dataLen)))
C.Tspi_Context_FreeMemory(key.context, cData)
return blob, nil
}
// Unseal decrypts data previously encrypted with this key as long as the
// PCR values match those the data was sealed against
func (key *Key) Unseal(data []byte) ([]byte, error) {
var encdata C.TSS_HENCDATA
var dataLen C.UINT32
var cData *C.BYTE
err := tspiError(C.Tspi_Context_CreateObject(key.context, C.TSS_OBJECT_TYPE_ENCDATA, C.TSS_ENCDATA_SEAL, (*C.TSS_HOBJECT)(&encdata)))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_SetAttribData((C.TSS_HOBJECT)(encdata), C.TSS_TSPATTRIB_ENCDATA_BLOB, C.TSS_TSPATTRIB_ENCDATABLOB_BLOB, (C.UINT32)(len(data)), (*C.BYTE)(unsafe.Pointer(&data[0]))))
if err != nil {
return nil, err
}
err = tspiError(C.Tspi_Data_Unseal(encdata, key.handle, &dataLen, &cData))
if err != nil {
return nil, err
}
blob := C.GoBytes(unsafe.Pointer(cData), (C.int(dataLen)))
C.Tspi_Context_FreeMemory(key.context, cData)
return blob, nil
}
// SetSignatureScheme sets the signature scheme on a newly created key. The scheme parameter should be one of tspiconst.TSS_SS_RSASSAPKCS1V15_SHA1
// or tspiconst.TSS_SS_RSASSAPKCS1V15_DER
func (key *Key) SetSignatureScheme(scheme int) error {
return tspiError(C.Tspi_SetAttribUint32((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_INFO, C.TSS_TSPATTRIB_KEYINFO_SIGSCHEME, (C.UINT32)(scheme)))
}
// GenerateKey generates a key pair on the TPM, wrapping it with the provided
// key
func (key *Key) GenerateKey(wrapkey *Key) (err error) {
err = tspiError(C.Tspi_Key_CreateKey((C.TSS_HKEY)(key.handle), (C.TSS_HKEY)(wrapkey.handle), 0))
return err
}
// Certify signs the public key with another key held by the TPM
func (key *Key) Certify(certifykey *Key, challenge []byte) ([]byte, []byte, error) {
var validation C.TSS_VALIDATION
challengeHash := sha1.Sum(challenge[:])
validation.ulExternalDataLength = sha1.Size
validation.rgbExternalData = (*C.BYTE)(&challengeHash[0])
err := tspiError(C.Tspi_Key_CertifyKey((C.TSS_HKEY)(key.handle), (C.TSS_HKEY)(certifykey.handle), &validation))
if err != nil {
return nil, nil, err
}
data := C.GoBytes(unsafe.Pointer(validation.rgbData), (C.int)(validation.ulDataLength))
validationdata := C.GoBytes(unsafe.Pointer(validation.rgbValidationData), (C.int)(validation.ulValidationDataLength))
C.Tspi_Context_FreeMemory(key.context, validation.rgbData)
C.Tspi_Context_FreeMemory(key.context, validation.rgbValidationData)
return data, validationdata, nil
}
// AssignPolicy assigns a TSS policy to the key.
func (key *Key) AssignPolicy(policy *Policy) error {
err := tspiError(C.Tspi_Policy_AssignToObject(policy.handle, (C.TSS_HOBJECT)(key.handle)))
return err
}
// Close closes the Key object.
func (key *Key) Close() error {
err := tspiError(C.Tspi_Context_CloseObject(key.context, key.handle))
return err
}
go-tspi-0.3.0/tspi/nv.go 0000664 0000000 0000000 00000003412 14067646345 0015044 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
import "unsafe"
// NV is a TSS NV object
type NV struct {
handle C.TSS_HNVSTORE
context C.TSS_HCONTEXT
}
// ReadValue reads length bytes from offset in the TPM NVRAM space
func (nv *NV) ReadValue(offset uint, length uint) ([]byte, error) {
var cdata *C.BYTE
defer C.Tspi_Context_FreeMemory(nv.context, cdata)
err := tspiError(C.Tspi_NV_ReadValue(nv.handle, (C.UINT32)(offset), (*C.UINT32)(unsafe.Pointer(&length)), &cdata))
if err != nil {
return nil, err
}
data := C.GoBytes(unsafe.Pointer(cdata), C.int(length))
return data, err
}
// SetIndex sets the TPM NVRAM index that will be referenced by ReadValue()
func (nv *NV) SetIndex(index uint) error {
err := tspiError(C.Tspi_SetAttribUint32((C.TSS_HOBJECT)(nv.handle), C.TSS_TSPATTRIB_NV_INDEX, 0, (C.UINT32)(index)))
return err
}
// AssignPolicy assigns a policy to the TPM NVRAM region
func (nv *NV) AssignPolicy(policy *Policy) error {
err := tspiError(C.Tspi_Policy_AssignToObject(policy.handle, (C.TSS_HOBJECT)(nv.handle)))
return err
}
// Close closes the NV object.
func (nv *NV) Close() error {
err := tspiError(C.Tspi_Context_CloseObject(nv.context, nv.handle))
return err
}
go-tspi-0.3.0/tspi/pcrs.go 0000664 0000000 0000000 00000003636 14067646345 0015400 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
import "unsafe"
// PCRs is a structure representing a PCR object and the PCR values
type PCRs struct {
handle C.TSS_HPCRS
context C.TSS_HCONTEXT
pcrs [24][]byte
pcrset [24]bool
}
// SetPCRs takes an array of integers referring to PCRs. Any queries performed
// with this PCR object will then query these PCRs.
func (pcrs *PCRs) SetPCRs(pcrset []int) error {
for pcr := range pcrs.pcrset {
pcrs.pcrset[pcr] = false
}
for _, pcr := range pcrset {
err := tspiError(C.Tspi_PcrComposite_SelectPcrIndex(pcrs.handle, (C.UINT32)(pcr)))
if err != nil {
return err
}
pcrs.pcrset[pcr] = true
}
return nil
}
// GetPCRValues obtains the PCR values for any PCRs that have been set.
func (pcrs *PCRs) GetPCRValues() ([][]byte, error) {
var buflen C.UINT32
var buf *C.BYTE
for pcr := range pcrs.pcrs {
if pcrs.pcrset[pcr] == false {
continue
}
err := tspiError(C.Tspi_PcrComposite_GetPcrValue(pcrs.handle, (C.UINT32)(pcr), &buflen, &buf))
if err != nil {
return nil, err
}
pcrs.pcrs[pcr] = C.GoBytes(unsafe.Pointer(buf), (C.int)(buflen))
C.Tspi_Context_FreeMemory(pcrs.context, buf)
}
return pcrs.pcrs[:], nil
}
// Close closes the PCRs object.
func (pcrs *PCRs) Close() error {
err := tspiError(C.Tspi_Context_CloseObject(pcrs.context, pcrs.handle))
return err
}
go-tspi-0.3.0/tspi/policy.go 0000664 0000000 0000000 00000002306 14067646345 0015721 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
// Policy is a TSS policy object
type Policy struct {
handle C.TSS_HPOLICY
context C.TSS_HCONTEXT
}
// SetSecret sets the secret for a policy. This policy may then be applied to
// another object.
func (policy *Policy) SetSecret(sectype int, secret []byte) error {
err := tspiError(C.Tspi_Policy_SetSecret(policy.handle, (C.TSS_FLAG)(sectype), (C.UINT32)(len(secret)), (*C.BYTE)(&secret[0])))
return err
}
// Close closes the Policy object.
func (policy *Policy) Close() error {
err := tspiError(C.Tspi_Context_CloseObject(policy.context, policy.handle))
return err
}
go-tspi-0.3.0/tspi/tpm.go 0000664 0000000 0000000 00000017370 14067646345 0015231 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
import "C"
import (
"bufio"
"crypto/sha1"
"encoding/binary"
"io"
"os"
"unsafe"
"github.com/google/go-tspi/tspiconst"
)
// TPM is a TSS TPM object
type TPM struct {
handle C.TSS_HTPM
context C.TSS_HCONTEXT
}
// GetEventLog returns an array of structures representing the contents of the
// TSS event log
func (tpm *TPM) GetEventLog() ([]tspiconst.Log, error) {
var count C.UINT32
var events *C.TSS_PCR_EVENT
var event C.TSS_PCR_EVENT
var log []tspiconst.Log
f, err := os.Open("/sys/kernel/security/tpm0/binary_bios_measurements")
if err != nil {
return nil, err
}
firmware_events := bufio.NewReader(f)
for {
var entry tspiconst.Log
var datalen int32
err := binary.Read(firmware_events, binary.LittleEndian, &entry.Pcr)
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
err = binary.Read(firmware_events, binary.LittleEndian, &entry.Eventtype)
if err != nil {
return nil, err
}
err = binary.Read(firmware_events, binary.LittleEndian, &entry.PcrValue)
if err != nil {
return nil, err
}
err = binary.Read(firmware_events, binary.LittleEndian, &datalen)
if err != nil {
return nil, err
}
data := make([]byte, datalen)
err = binary.Read(firmware_events, binary.LittleEndian, &data)
if err != nil {
return nil, err
}
entry.Event = data[:]
log = append(log, entry)
}
err = tspiError(C.Tspi_TPM_GetEventLog(tpm.handle, &count, &events))
if err != nil {
return nil, err
}
if count == 0 {
return log, nil
}
length := count * C.UINT32(unsafe.Sizeof(event))
slice := (*[1 << 26]C.TSS_PCR_EVENT)(unsafe.Pointer(events))[:length:length]
for i := 0; i < int(count); i++ {
var entry tspiconst.Log
entry.Pcr = int32(slice[i].ulPcrIndex)
entry.Eventtype = int32(slice[i].eventType)
copy(entry.PcrValue[:], C.GoBytes(unsafe.Pointer(slice[i].rgbPcrValue), C.int(slice[i].ulPcrValueLength)))
entry.Event = C.GoBytes(unsafe.Pointer(slice[i].rgbEvent), C.int(slice[i].ulEventLength))
log = append(log, entry)
}
C.Tspi_Context_FreeMemory(tpm.context, (*C.BYTE)(unsafe.Pointer(events)))
return log, nil
}
// ExtendPCR extends a pcr. If event is nil, data must be pre-hashed with
// SHA1. If event is not nil, event is used to populate the TSS event
// log. If both data and event are provided, both will be used to create the
// extend hash.
func (tpm *TPM) ExtendPCR(pcr int, data []byte, eventtype int, event []byte) error {
var outlen C.UINT32
var pcrval *C.BYTE
var eventstruct C.TSS_PCR_EVENT
var err error
shasum := sha1.Sum(data)
if event != nil {
var pcrdata *C.BYTE
var pcrdatalen C.UINT32
eventstruct.versionInfo.bMajor = 1
eventstruct.versionInfo.bMinor = 2
eventstruct.versionInfo.bRevMajor = 1
eventstruct.versionInfo.bRevMinor = 0
eventstruct.ulPcrIndex = C.UINT32(pcr)
eventstruct.rgbPcrValue = (*C.BYTE)(&shasum[0])
eventstruct.eventType = C.TSS_EVENTTYPE(eventtype)
eventstruct.ulEventLength = C.UINT32(len(event))
eventstruct.rgbEvent = (*C.BYTE)(&event[0])
if data == nil || len(data) == 0 {
pcrdata = nil
pcrdatalen = C.UINT32(0)
} else {
pcrdata = (*C.BYTE)(&data[0])
pcrdatalen = C.UINT32(len(data))
}
err = tspiError(C.Tspi_TPM_PcrExtend(tpm.handle, C.UINT32(pcr), pcrdatalen, pcrdata, &eventstruct, &outlen, &pcrval))
} else {
err = tspiError(C.Tspi_TPM_PcrExtend(tpm.handle, C.UINT32(pcr), C.UINT32(len(shasum)), (*C.BYTE)(&shasum[0]), nil, &outlen, &pcrval))
}
C.Tspi_Context_FreeMemory(tpm.context, pcrval)
return err
}
// GetPCRValues obtains the PCR values from the TPM.
func (tpm *TPM) GetPCRValues() ([][]byte, error) {
var (
buflen C.UINT32
buf *C.BYTE
pcrs [24][]byte
)
for pcr := 0; pcr < 24; pcr++ {
err := tspiError(C.Tspi_TPM_PcrRead(tpm.handle, (C.UINT32)(pcr), &buflen, &buf))
if err != nil {
return nil, err
}
pcrs[pcr] = C.GoBytes(unsafe.Pointer(buf), (C.int)(buflen))
C.Tspi_Context_FreeMemory(tpm.context, buf)
}
return pcrs[:], nil
}
//GetQuote takes an encrypted key blob representing the AIK, a set of PCRs
//and a challenge and returns a blob containing a hash of the PCR hashes and
//the challenge, and a validation blob signed by the AIK.
func (tpm *TPM) GetQuote(aik *Key, pcrs *PCRs, challenge []byte) ([]byte, []byte, error) {
var validation C.TSS_VALIDATION
challangeHash := sha1.Sum(challenge[:])
validation.ulExternalDataLength = sha1.Size
validation.rgbExternalData = (*C.BYTE)(C.CBytes(challangeHash[:]))
defer C.free(unsafe.Pointer(validation.rgbExternalData))
err := tspiError(C.Tspi_TPM_Quote(tpm.handle, aik.handle, pcrs.handle, &validation))
if err != nil {
return nil, nil, err
}
data := C.GoBytes(unsafe.Pointer(validation.rgbData), (C.int)(validation.ulDataLength))
validationOutput := C.GoBytes(unsafe.Pointer(validation.rgbValidationData), (C.int)(validation.ulValidationDataLength))
C.Tspi_Context_FreeMemory(tpm.context, validation.rgbData)
C.Tspi_Context_FreeMemory(tpm.context, validation.rgbValidationData)
return data, validationOutput, nil
}
// ActivateIdentity accepts an encrypted key blob representing the AIK and
// two blobs representing the asymmetric and symmetric challenges associated
// with the AIK. If the TPM is able to decrypt the challenges and the
// challenges correspond to the AIK, the TPM will return the original
// challenge secret.
func (tpm *TPM) ActivateIdentity(aik *Key, asymblob []byte, symblob []byte) (secret []byte, err error) {
var creds *C.BYTE
var credlen C.UINT32
err = tspiError(C.Tspi_TPM_ActivateIdentity(tpm.handle, aik.handle, (C.UINT32)(len(asymblob)), (*C.BYTE)(&asymblob[0]), (C.UINT32)(len(symblob)), (*C.BYTE)(&symblob[0]), &credlen, &creds))
if err != nil {
return nil, err
}
plaintext := C.GoBytes(unsafe.Pointer(creds), (C.int)(credlen))
C.Tspi_Context_FreeMemory(tpm.context, creds)
return plaintext, nil
}
// GetPolicy returns the TSS policy associated with the TPM.
func (tpm *TPM) GetPolicy(poltype int) (*Policy, error) {
var policyHandle C.TSS_HPOLICY
err := tspiError(C.Tspi_GetPolicyObject((C.TSS_HOBJECT)(tpm.handle), (C.TSS_FLAG)(poltype), &policyHandle))
return &Policy{handle: policyHandle, context: tpm.context}, err
}
// TakeOwnership transitions a TPM from unowned state to owned, installing the
// encrypted key blob as the SRK.
func (tpm *TPM) TakeOwnership(srk *Key) error {
err := tspiError(C.Tspi_TPM_TakeOwnership(tpm.handle, srk.handle, 0))
return err
}
// AssignPolicy assigns a TSS policy to the TPM.
func (tpm *TPM) AssignPolicy(policy *Policy) error {
err := tspiError(C.Tspi_Policy_AssignToObject(policy.handle, (C.TSS_HOBJECT)(tpm.handle)))
return err
}
// CollateIdentityRequest creates a signing request for the provided AIKq
func (tpm *TPM) CollateIdentityRequest(srk *Key, pubkey *Key, aik *Key) ([]byte, error) {
var certLen C.UINT32
var cCertReq *C.BYTE
err := tspiError(C.Tspi_TPM_CollateIdentityRequest(tpm.handle, srk.handle, pubkey.handle, 0, nil, aik.handle, C.TSS_ALG_AES, &certLen, &cCertReq))
certReq := C.GoBytes(unsafe.Pointer(cCertReq), (C.int)(certLen))
C.Tspi_Context_FreeMemory(tpm.context, cCertReq)
return certReq, err
}
// Close closes the TPM object.
func (tpm *TPM) Close() error {
err := tspiError(C.Tspi_Context_CloseObject(tpm.context, tpm.handle))
return err
}
go-tspi-0.3.0/tspi/tspi.go 0000664 0000000 0000000 00000040446 14067646345 0015410 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspi
// #include
// #cgo LDFLAGS: -ltspi
import "C"
import "errors"
import "fmt"
func tspiError(tssRet C.TSS_RESULT) error {
ret := (int)(tssRet)
if ret == 0 {
return nil
}
if (ret & 0xf000) != 0 {
ret &= ^(0xf000)
switch {
case ret == C.TSS_E_FAIL:
return errors.New("TSS_E_FAIL")
case ret == C.TSS_E_BAD_PARAMETER:
return errors.New("TSS_E_BAD_PARAMETER")
case ret == C.TSS_E_INTERNAL_ERROR:
return errors.New("TSS_E_INTERNAL_ERROR")
case ret == C.TSS_E_OUTOFMEMORY:
return errors.New("TSS_E_OUTOFMEMORY")
case ret == C.TSS_E_NOTIMPL:
return errors.New("TSS_E_NOTIMPL")
case ret == C.TSS_E_KEY_ALREADY_REGISTERED:
return errors.New("TSS_E_KEY_ALREADY_REGISTERED")
case ret == C.TSS_E_TPM_UNEXPECTED:
return errors.New("TSS_E_TPM_UNEXPECTED")
case ret == C.TSS_E_COMM_FAILURE:
return errors.New("TSS_E_COMM_FAILURE")
case ret == C.TSS_E_TIMEOUT:
return errors.New("TSS_E_TIMEOUT")
case ret == C.TSS_E_TPM_UNSUPPORTED_FEATURE:
return errors.New("TSS_E_TPM_UNSUPPORTED_FEATURE")
case ret == C.TSS_E_CANCELED:
return errors.New("TSS_E_CANCELED")
case ret == C.TSS_E_PS_KEY_NOTFOUND:
return errors.New("TSS_E_PS_KEY_NOTFOUND")
case ret == C.TSS_E_PS_KEY_EXISTS:
return errors.New("TSS_E_PS_KEY_EXISTS")
case ret == C.TSS_E_PS_BAD_KEY_STATE:
return errors.New("TSS_E_PS_BAD_KEY_STATE")
case ret == C.TSS_E_INVALID_OBJECT_TYPE:
return errors.New("TSS_E_INVALID_OBJECT_TYPE")
case ret == C.TSS_E_NO_CONNECTION:
return errors.New("TSS_E_NO_CONNECTION")
case ret == C.TSS_E_CONNECTION_FAILED:
return errors.New("TSS_E_CONNECTION_FAILED")
case ret == C.TSS_E_CONNECTION_BROKEN:
return errors.New("TSS_E_CONNECTION_BROKEN")
case ret == C.TSS_E_HASH_INVALID_ALG:
return errors.New("TSS_E_HASH_INVALID_ALG")
case ret == C.TSS_E_HASH_INVALID_LENGTH:
return errors.New("TSS_E_HASH_INVALID_LENGTH")
case ret == C.TSS_E_HASH_NO_DATA:
return errors.New("TSS_E_HASH_NO_DATA")
case ret == C.TSS_E_INVALID_ATTRIB_FLAG:
return errors.New("TSS_E_INVALID_ATTRIB_FLAG")
case ret == C.TSS_E_INVALID_ATTRIB_SUBFLAG:
return errors.New("TSS_E_INVALID_ATTRIB_SUBFLAG")
case ret == C.TSS_E_INVALID_ATTRIB_DATA:
return errors.New("TSS_E_INVALID_ATTRIB_DATA")
case ret == C.TSS_E_INVALID_OBJECT_INITFLAG:
return errors.New("TSS_E_INVALID_OBJECT_INITFLAG")
case ret == C.TSS_E_NO_PCRS_SET:
return errors.New("TSS_E_NO_PCRS_SET")
case ret == C.TSS_E_KEY_NOT_LOADED:
return errors.New("TSS_E_KEY_NOT_LOADED")
case ret == C.TSS_E_KEY_NOT_SET:
return errors.New("TSS_E_KEY_NOT_SET")
case ret == C.TSS_E_VALIDATION_FAILED:
return errors.New("TSS_E_VALIDATION_FAILED")
case ret == C.TSS_E_TSP_AUTHREQUIRED:
return errors.New("TSS_E_TSP_AUTHREQUIRED")
case ret == C.TSS_E_TSP_AUTH2REQUIRED:
return errors.New("TSS_E_TSP_AUTH2REQUIRED")
case ret == C.TSS_E_TSP_AUTHFAIL:
return errors.New("TSS_E_TSP_AUTHFAIL")
case ret == C.TSS_E_TSP_AUTH2FAIL:
return errors.New("TSS_E_TSP_AUTH2FAIL")
case ret == C.TSS_E_KEY_NO_MIGRATION_POLICY:
return errors.New("TSS_E_KEY_NO_MIGRATION_POLICY")
case ret == C.TSS_E_POLICY_NO_SECRET:
return errors.New("TSS_E_POLICY_NO_SECRET")
case ret == C.TSS_E_INVALID_OBJ_ACCESS:
return errors.New("TSS_E_INVALID_OBJ_ACCESS")
case ret == C.TSS_E_INVALID_ENCSCHEME:
return errors.New("TSS_E_INVALID_ENCSCHEME")
case ret == C.TSS_E_INVALID_SIGSCHEME:
return errors.New("TSS_E_INVALID_SIGSCHEME")
case ret == C.TSS_E_ENC_INVALID_LENGTH:
return errors.New("TSS_E_ENC_INVALID_LENGTH")
case ret == C.TSS_E_ENC_NO_DATA:
return errors.New("TSS_E_ENC_NO_DATA")
case ret == C.TSS_E_ENC_INVALID_TYPE:
return errors.New("TSS_E_ENC_INVALID_TYPE")
case ret == C.TSS_E_INVALID_KEYUSAGE:
return errors.New("TSS_E_INVALID_KEYUSAGE")
case ret == C.TSS_E_VERIFICATION_FAILED:
return errors.New("TSS_E_VERIFICATION_FAILED")
case ret == C.TSS_E_HASH_NO_IDENTIFIER:
return errors.New("TSS_E_HASH_NO_IDENTIFIER")
case ret == C.TSS_E_INVALID_HANDLE:
return errors.New("TSS_E_INVALID_HANDLE")
case ret == C.TSS_E_SILENT_CONTEXT:
return errors.New("TSS_E_SILENT_CONTEXT")
case ret == C.TSS_E_EK_CHECKSUM:
return errors.New("TSS_E_EK_CHECKSUM")
case ret == C.TSS_E_DELEGATION_NOTSET:
return errors.New("TSS_E_DELEGATION_NOTSET")
case ret == C.TSS_E_DELFAMILY_NOTFOUND:
return errors.New("TSS_E_DELFAMILY_NOTFOUND")
case ret == C.TSS_E_DELFAMILY_ROWEXISTS:
return errors.New("TSS_E_DELFAMILY_ROWEXISTS")
case ret == C.TSS_E_VERSION_MISMATCH:
return errors.New("TSS_E_VERSION_MISMATCH")
case ret == C.TSS_E_DAA_AR_DECRYPTION_ERROR:
return errors.New("TSS_E_DAA_AR_DECRYPTION_ERROR")
case ret == C.TSS_E_DAA_AUTHENTICATION_ERROR:
return errors.New("TSS_E_DAA_AUTHENTICATION_ERROR")
case ret == C.TSS_E_DAA_CHALLENGE_RESPONSE_ERROR:
return errors.New("TSS_E_DAA_CHALLENGE_RESPONSE_ERROR")
case ret == C.TSS_E_DAA_CREDENTIAL_PROOF_ERROR:
return errors.New("TSS_E_DAA_CREDENTIAL_PROOF_ERROR")
case ret == C.TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR:
return errors.New("TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR")
case ret == C.TSS_E_DAA_ISSUER_KEY_ERROR:
return errors.New("TSS_E_DAA_ISSUER_KEY_ERROR")
case ret == C.TSS_E_DAA_PSEUDONYM_ERROR:
return errors.New("TSS_E_DAA_PSEUDONYM_ERROR")
case ret == C.TSS_E_INVALID_RESOURCE:
return errors.New("TSS_E_INVALID_RESOURCE")
case ret == C.TSS_E_NV_AREA_EXIST:
return errors.New("TSS_E_NV_AREA_EXIST")
case ret == C.TSS_E_NV_AREA_NOT_EXIST:
return errors.New("TSS_E_NV_AREA_NOT_EXIST")
case ret == C.TSS_E_TSP_TRANS_AUTHFAIL:
return errors.New("TSS_E_TSP_TRANS_AUTHFAIL")
case ret == C.TSS_E_TSP_TRANS_AUTHREQUIRED:
return errors.New("TSS_E_TSP_TRANS_AUTHREQUIRED")
case ret == C.TSS_E_TSP_TRANS_NOTEXCLUSIVE:
return errors.New("TSS_E_TSP_TRANS_NOTEXCLUSIVE")
case ret == C.TSS_E_TSP_TRANS_FAIL:
return errors.New("TSS_E_TSP_TRANS_FAIL")
case ret == C.TSS_E_TSP_TRANS_NO_PUBKEY:
return errors.New("TSS_E_TSP_TRANS_NO_PUBKEY")
case ret == C.TSS_E_NO_ACTIVE_COUNTER:
return errors.New("TSS_E_NO_ACTIVE_COUNTER")
}
return fmt.Errorf("Unknown TSS error: %x", ret)
}
switch {
case ret == C.TPM_E_NON_FATAL:
return errors.New("TPM_E_NON_FATAL")
case ret == C.TPM_E_AUTHFAIL:
return errors.New("TPM_E_AUTHFAIL")
case ret == C.TPM_E_BADINDEX:
return errors.New("TPM_E_BADINDEX")
case ret == C.TPM_E_BAD_PARAMETER:
return errors.New("TPM_E_BAD_PARAMETER")
case ret == C.TPM_E_AUDITFAILURE:
return errors.New("TPM_E_AUDITFAILURE")
case ret == C.TPM_E_CLEAR_DISABLED:
return errors.New("TPM_E_CLEAR_DISABLED")
case ret == C.TPM_E_DEACTIVATED:
return errors.New("TPM_E_DEACTIVATED")
case ret == C.TPM_E_DISABLED:
return errors.New("TPM_E_DISABLED")
case ret == C.TPM_E_DISABLED_CMD:
return errors.New("TPM_E_DISABLED_CMD")
case ret == C.TPM_E_FAIL:
return errors.New("TPM_E_FAIL")
case ret == C.TPM_E_BAD_ORDINAL:
return errors.New("TPM_E_BAD_ORDINAL")
case ret == C.TPM_E_INSTALL_DISABLED:
return errors.New("TPM_E_INSTALL_DISABLED")
case ret == C.TPM_E_INVALID_KEYHANDLE:
return errors.New("TPM_E_INVALID_KEYHANDLE")
case ret == C.TPM_E_KEYNOTFOUND:
return errors.New("TPM_E_KEYNOTFOUND")
case ret == C.TPM_E_INAPPROPRIATE_ENC:
return errors.New("TPM_E_INAPPROPRIATE_ENC")
case ret == C.TPM_E_MIGRATEFAIL:
return errors.New("TPM_E_MIGRATEFAIL")
case ret == C.TPM_E_INVALID_PCR_INFO:
return errors.New("TPM_E_INVALID_PCR_INFO")
case ret == C.TPM_E_NOSPACE:
return errors.New("TPM_E_NOSPACE")
case ret == C.TPM_E_NOSRK:
return errors.New("TPM_E_NOSRK")
case ret == C.TPM_E_NOTSEALED_BLOB:
return errors.New("TPM_E_NOTSEALED_BLOB")
case ret == C.TPM_E_OWNER_SET:
return errors.New("TPM_E_OWNER_SET")
case ret == C.TPM_E_RESOURCES:
return errors.New("TPM_E_RESOURCES")
case ret == C.TPM_E_SHORTRANDOM:
return errors.New("TPM_E_SHORTRANDOM")
case ret == C.TPM_E_SIZE:
return errors.New("TPM_E_SIZE")
case ret == C.TPM_E_WRONGPCRVAL:
return errors.New("TPM_E_WRONGPCRVAL")
case ret == C.TPM_E_BAD_PARAM_SIZE:
return errors.New("TPM_E_BAD_PARAM_SIZE")
case ret == C.TPM_E_SHA_THREAD:
return errors.New("TPM_E_SHA_THREAD")
case ret == C.TPM_E_SHA_ERROR:
return errors.New("TPM_E_SHA_ERROR")
case ret == C.TPM_E_FAILEDSELFTEST:
return errors.New("TPM_E_FAILEDSELFTEST")
case ret == C.TPM_E_AUTH2FAIL:
return errors.New("TPM_E_AUTH2FAIL")
case ret == C.TPM_E_BADTAG:
return errors.New("TPM_E_BADTAG")
case ret == C.TPM_E_IOERROR:
return errors.New("TPM_E_IOERROR")
case ret == C.TPM_E_ENCRYPT_ERROR:
return errors.New("TPM_E_ENCRYPT_ERROR")
case ret == C.TPM_E_DECRYPT_ERROR:
return errors.New("TPM_E_DECRYPT_ERROR")
case ret == C.TPM_E_INVALID_AUTHHANDLE:
return errors.New("TPM_E_INVALID_AUTHHANDLE")
case ret == C.TPM_E_NO_ENDORSEMENT:
return errors.New("TPM_E_NO_ENDORSEMENT")
case ret == C.TPM_E_INVALID_KEYUSAGE:
return errors.New("TPM_E_INVALID_KEYUSAGE")
case ret == C.TPM_E_WRONG_ENTITYTYPE:
return errors.New("TPM_E_WRONG_ENTITYTYPE")
case ret == C.TPM_E_INVALID_POSTINIT:
return errors.New("TPM_E_INVALID_POSTINIT")
case ret == C.TPM_E_INAPPROPRIATE_SIG:
return errors.New("TPM_E_INAPPROPRIATE_SIG")
case ret == C.TPM_E_BAD_KEY_PROPERTY:
return errors.New("TPM_E_BAD_KEY_PROPERTY")
case ret == C.TPM_E_BAD_MIGRATION:
return errors.New("TPM_E_BAD_MIGRATION")
case ret == C.TPM_E_BAD_SCHEME:
return errors.New("TPM_E_BAD_SCHEME")
case ret == C.TPM_E_BAD_DATASIZE:
return errors.New("TPM_E_BAD_DATASIZE")
case ret == C.TPM_E_BAD_MODE:
return errors.New("TPM_E_BAD_MODE")
case ret == C.TPM_E_BAD_PRESENCE:
return errors.New("TPM_E_BAD_PRESENCE")
case ret == C.TPM_E_BAD_VERSION:
return errors.New("TPM_E_BAD_VERSION")
case ret == C.TPM_E_NO_WRAP_TRANSPORT:
return errors.New("TPM_E_NO_WRAP_TRANSPORT")
case ret == C.TPM_E_AUDITFAIL_UNSUCCESSFUL:
return errors.New("TPM_E_AUDITFAIL_UNSUCCESSFUL")
case ret == C.TPM_E_AUDITFAIL_SUCCESSFUL:
return errors.New("TPM_E_AUDITFAIL_SUCCESSFUL")
case ret == C.TPM_E_NOTRESETABLE:
return errors.New("TPM_E_NOTRESETABLE")
case ret == C.TPM_E_NOTLOCAL:
return errors.New("TPM_E_NOTLOCAL")
case ret == C.TPM_E_BAD_TYPE:
return errors.New("TPM_E_BAD_TYPE")
case ret == C.TPM_E_INVALID_RESOURCE:
return errors.New("TPM_E_INVALID_RESOURCE")
case ret == C.TPM_E_NOTFIPS:
return errors.New("TPM_E_NOTFIPS")
case ret == C.TPM_E_INVALID_FAMILY:
return errors.New("TPM_E_INVALID_FAMILY")
case ret == C.TPM_E_NO_NV_PERMISSION:
return errors.New("TPM_E_NO_NV_PERMISSION")
case ret == C.TPM_E_REQUIRES_SIGN:
return errors.New("TPM_E_REQUIRES_SIGN")
case ret == C.TPM_E_KEY_NOTSUPPORTED:
return errors.New("TPM_E_KEY_NOTSUPPORTED")
case ret == C.TPM_E_AUTH_CONFLICT:
return errors.New("TPM_E_AUTH_CONFLICT")
case ret == C.TPM_E_AREA_LOCKED:
return errors.New("TPM_E_AREA_LOCKED")
case ret == C.TPM_E_BAD_LOCALITY:
return errors.New("TPM_E_BAD_LOCALITY")
case ret == C.TPM_E_READ_ONLY:
return errors.New("TPM_E_READ_ONLY")
case ret == C.TPM_E_PER_NOWRITE:
return errors.New("TPM_E_PER_NOWRITE")
case ret == C.TPM_E_FAMILYCOUNT:
return errors.New("TPM_E_FAMILYCOUNT")
case ret == C.TPM_E_WRITE_LOCKED:
return errors.New("TPM_E_WRITE_LOCKED")
case ret == C.TPM_E_BAD_ATTRIBUTES:
return errors.New("TPM_E_BAD_ATTRIBUTES")
case ret == C.TPM_E_INVALID_STRUCTURE:
return errors.New("TPM_E_INVALID_STRUCTURE")
case ret == C.TPM_E_KEY_OWNER_CONTROL:
return errors.New("TPM_E_KEY_OWNER_CONTROL")
case ret == C.TPM_E_BAD_COUNTER:
return errors.New("TPM_E_BAD_COUNTER")
case ret == C.TPM_E_NOT_FULLWRITE:
return errors.New("TPM_E_NOT_FULLWRITE")
case ret == C.TPM_E_CONTEXT_GAP:
return errors.New("TPM_E_CONTEXT_GAP")
case ret == C.TPM_E_MAXNVWRITES:
return errors.New("TPM_E_MAXNVWRITES")
case ret == C.TPM_E_NOOPERATOR:
return errors.New("TPM_E_NOOPERATOR")
case ret == C.TPM_E_RESOURCEMISSING:
return errors.New("TPM_E_RESOURCEMISSING")
case ret == C.TPM_E_DELEGATE_LOCK:
return errors.New("TPM_E_DELEGATE_LOCK")
case ret == C.TPM_E_DELEGATE_FAMILY:
return errors.New("TPM_E_DELEGATE_FAMILY")
case ret == C.TPM_E_DELEGATE_ADMIN:
return errors.New("TPM_E_DELEGATE_ADMIN")
case ret == C.TPM_E_TRANSPORT_NOTEXCLUSIVE:
return errors.New("TPM_E_TRANSPORT_NOTEXCLUSIVE")
case ret == C.TPM_E_OWNER_CONTROL:
return errors.New("TPM_E_OWNER_CONTROL")
case ret == C.TPM_E_DAA_RESOURCES:
return errors.New("TPM_E_DAA_RESOURCES")
case ret == C.TPM_E_DAA_INPUT_DATA0:
return errors.New("TPM_E_DAA_INPUT_DATA0")
case ret == C.TPM_E_DAA_INPUT_DATA1:
return errors.New("TPM_E_DAA_INPUT_DATA1")
case ret == C.TPM_E_DAA_ISSUER_SETTINGS:
return errors.New("TPM_E_DAA_ISSUER_SETTINGS")
case ret == C.TPM_E_DAA_TPM_SETTINGS:
return errors.New("TPM_E_DAA_TPM_SETTINGS")
case ret == C.TPM_E_DAA_STAGE:
return errors.New("TPM_E_DAA_STAGE")
case ret == C.TPM_E_DAA_ISSUER_VALIDITY:
return errors.New("TPM_E_DAA_ISSUER_VALIDITY")
case ret == C.TPM_E_DAA_WRONG_W:
return errors.New("TPM_E_DAA_WRONG_W")
case ret == C.TPM_E_BAD_HANDLE:
return errors.New("TPM_E_BAD_HANDLE")
case ret == C.TPM_E_BAD_DELEGATE:
return errors.New("TPM_E_BAD_DELEGATE")
case ret == C.TPM_E_BADCONTEXT:
return errors.New("TPM_E_BADCONTEXT")
case ret == C.TPM_E_TOOMANYCONTEXTS:
return errors.New("TPM_E_TOOMANYCONTEXTS")
case ret == C.TPM_E_MA_TICKET_SIGNATURE:
return errors.New("TPM_E_MA_TICKET_SIGNATURE")
case ret == C.TPM_E_MA_DESTINATION:
return errors.New("TPM_E_MA_DESTINATION")
case ret == C.TPM_E_MA_SOURCE:
return errors.New("TPM_E_MA_SOURCE")
case ret == C.TPM_E_MA_AUTHORITY:
return errors.New("TPM_E_MA_AUTHORITY")
case ret == C.TPM_E_PERMANENTEK:
return errors.New("TPM_E_PERMANENTEK")
case ret == C.TPM_E_BAD_SIGNATURE:
return errors.New("TPM_E_BAD_SIGNATURE")
case ret == C.TPM_E_NOCONTEXTSPACE:
return errors.New("TPM_E_NOCONTEXTSPACE")
case ret == C.TPM_E_RETRY:
return errors.New("TPM_E_RETRY")
case ret == C.TPM_E_NEEDS_SELFTEST:
return errors.New("TPM_E_NEEDS_SELFTEST")
case ret == C.TPM_E_DOING_SELFTEST:
return errors.New("TPM_E_DOING_SELFTEST")
case ret == C.TPM_E_DEFEND_LOCK_RUNNING:
return errors.New("TPM_E_DEFEND_LOCK_RUNNING")
}
return fmt.Errorf("Unknown error: %x", ret)
}
var TSS_UUID_SRK = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 1},
}
var TSS_UUID_SK = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 2},
}
var TSS_UUID_RK = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 3},
}
var TSS_UUID_CRK = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 8},
}
var TSS_UUID_USK1 = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 4},
}
var TSS_UUID_USK2 = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 5},
}
var TSS_UUID_USK3 = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 6},
}
var TSS_UUID_USK4 = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 7},
}
var TSS_UUID_USK5 = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 9},
}
var TSS_UUID_USK6 = C.TSS_UUID{
ulTimeLow: 0,
usTimeMid: 0,
usTimeHigh: 0,
bClockSeqHigh: 0,
bClockSeqLow: 0,
rgbNode: [6]C.BYTE{0, 0, 0, 0, 0, 10},
}
go-tspi-0.3.0/tspiconst/ 0000775 0000000 0000000 00000000000 14067646345 0015141 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/tspiconst/tspiconst.go 0000664 0000000 0000000 00000104247 14067646345 0017526 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 tspiconst
const (
TSS_OBJECT_TYPE_POLICY = 0x01
TSS_OBJECT_TYPE_RSAKEY = 0x02
TSS_OBJECT_TYPE_ENCDATA = 0x03
TSS_OBJECT_TYPE_PCRS = 0x04
TSS_OBJECT_TYPE_HASH = 0x05
TSS_OBJECT_TYPE_DELFAMILY = 0x06
TSS_OBJECT_TYPE_NV = 0x07
TSS_OBJECT_TYPE_MIGDATA = 0x08
TSS_OBJECT_TYPE_DAA_CERTIFICATE = 0x09
TSS_OBJECT_TYPE_DAA_ISSUER_KEY = 0x0a
TSS_OBJECT_TYPE_DAA_ARA_KEY = 0x0b
TSS_KEY_NO_AUTHORIZATION = 0x00000000
TSS_KEY_AUTHORIZATION = 0x00000001
TSS_KEY_AUTHORIZATION_PRIV_USE_ONLY = 0x00000002
TSS_KEY_NON_VOLATILE = 0x00000000
TSS_KEY_VOLATILE = 0x00000004
TSS_KEY_NOT_MIGRATABLE = 0x00000000
TSS_KEY_MIGRATABLE = 0x00000008
TSS_KEY_TYPE_DEFAULT = 0x00000000
TSS_KEY_TYPE_SIGNING = 0x00000010
TSS_KEY_TYPE_STORAGE = 0x00000020
TSS_KEY_TYPE_IDENTITY = 0x00000030
TSS_KEY_TYPE_AUTHCHANGE = 0x00000040
TSS_KEY_TYPE_BIND = 0x00000050
TSS_KEY_TYPE_LEGACY = 0x00000060
TSS_KEY_TYPE_MIGRATE = 0x00000070
TSS_KEY_TYPE_BITMASK = 0x000000F0
TSS_KEY_SIZE_DEFAULT = 0x00000000
TSS_KEY_SIZE_512 = 0x00000100
TSS_KEY_SIZE_1024 = 0x00000200
TSS_KEY_SIZE_2048 = 0x00000300
TSS_KEY_SIZE_4096 = 0x00000400
TSS_KEY_SIZE_8192 = 0x00000500
TSS_KEY_SIZE_16384 = 0x00000600
TSS_KEY_SIZE_BITMASK = 0x00000F00
TSS_KEY_NOT_CERTIFIED_MIGRATABLE = 0x00000000
TSS_KEY_CERTIFIED_MIGRATABLE = 0x00001000
TSS_KEY_STRUCT_DEFAULT = 0x00000000
TSS_KEY_STRUCT_KEY = 0x00004000
TSS_KEY_STRUCT_KEY12 = 0x00008000
TSS_KEY_STRUCT_BITMASK = 0x0001C000
TSS_KEY_EMPTY_KEY = 0x00000000
TSS_KEY_TSP_SRK = 0x04000000
TSS_KEY_TEMPLATE_BITMASK = 0xFC000000
TSS_ENCDATA_SEAL = 0x00000001
TSS_ENCDATA_BIND = 0x00000002
TSS_ENCDATA_LEGACY = 0x00000003
TSS_HASH_DEFAULT = 0x00000000
TSS_HASH_SHA1 = 0x00000001
TSS_HASH_OTHER = 0xFFFFFFFF
TSS_POLICY_USAGE = 0x00000001
TSS_POLICY_MIGRATION = 0x00000002
TSS_POLICY_OPERATOR = 0x00000003
TSS_PCRS_STRUCT_DEFAULT = 0x00000000
TSS_PCRS_STRUCT_INFO = 0x00000001
TSS_PCRS_STRUCT_INFO_LONG = 0x00000002
TSS_PCRS_STRUCT_INFO_SHORT = 0x00000003
TSS_TSPATTRIB_CONTEXT_SILENT_MODE = 0x00000001
TSS_TSPATTRIB_CONTEXT_MACHINE_NAME = 0x00000002
TSS_TSPATTRIB_CONTEXT_VERSION_MODE = 0x00000003
TSS_TSPATTRIB_CONTEXT_TRANSPORT = 0x00000004
TSS_TSPATTRIB_CONTEXT_CONNECTION_VERSION = 0x00000005
TSS_TSPATTRIB_SECRET_HASH_MODE = 0x00000006
TSS_TSPATTRIB_CONTEXTTRANS_CONTROL = 0x00000008
TSS_TSPATTRIB_CONTEXTTRANS_MODE = 0x00000010
TSS_TSPATTRIB_CONTEXT_NOT_SILENT = 0x00000000
TSS_TSPATTRIB_CONTEXT_SILENT = 0x00000001
TSS_TSPATTRIB_CONTEXT_VERSION_AUTO = 0x00000001
TSS_TSPATTRIB_CONTEXT_VERSION_V1_1 = 0x00000002
TSS_TSPATTRIB_CONTEXT_VERSION_V1_2 = 0x00000003
TSS_TSPATTRIB_DISABLE_TRANSPORT = 0x00000016
TSS_TSPATTRIB_ENABLE_TRANSPORT = 0x00000032
TSS_TSPATTRIB_TRANSPORT_NO_DEFAULT_ENCRYPTION = 0x00000000
TSS_TSPATTRIB_TRANSPORT_DEFAULT_ENCRYPTION = 0x00000001
TSS_TSPATTRIB_TRANSPORT_AUTHENTIC_CHANNEL = 0x00000002
TSS_TSPATTRIB_TRANSPORT_EXCLUSIVE = 0x00000004
TSS_TSPATTRIB_TRANSPORT_STATIC_AUTH = 0x00000008
TSS_CONNECTION_VERSION_1_1 = 0x00000001
TSS_CONNECTION_VERSION_1_2 = 0x00000002
TSS_TSPATTRIB_SECRET_HASH_MODE_POPUP = 0x00000001
TSS_TSPATTRIB_HASH_MODE_NOT_NULL = 0x00000000
TSS_TSPATTRIB_HASH_MODE_NULL = 0x00000001
TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY = 0x00000001
TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY = 0x00000002
TSS_TSPATTRIB_TPM_ORDINAL_AUDIT_STATUS = 0x00000003
TSS_TSPATTRIB_TPM_CREDENTIAL = 0x00001000
TPM_CAP_PROP_TPM_CLEAR_ORDINAL_AUDIT = 0x00000000
TPM_CAP_PROP_TPM_SET_ORDINAL_AUDIT = 0x00000001
TSS_TPMATTRIB_EKCERT = 0x00000001
TSS_TPMATTRIB_TPM_CC = 0x00000002
TSS_TPMATTRIB_PLATFORMCERT = 0x00000003
TSS_TPMATTRIB_PLATFORM_CC = 0x00000004
TSS_TSPATTRIB_POLICY_CALLBACK_HMAC = 0x00000080
TSS_TSPATTRIB_POLICY_CALLBACK_XOR_ENC = 0x00000100
TSS_TSPATTRIB_POLICY_CALLBACK_TAKEOWNERSHIP = 0x00000180
TSS_TSPATTRIB_POLICY_CALLBACK_CHANGEAUTHASYM = 0x00000200
TSS_TSPATTRIB_POLICY_SECRET_LIFETIME = 0x00000280
TSS_TSPATTRIB_POLICY_POPUPSTRING = 0x00000300
TSS_TSPATTRIB_POLICY_CALLBACK_SEALX_MASK = 0x00000380
TSS_TSPATTRIB_POLICY_DELEGATION_INFO = 0x00000001
TSS_TSPATTRIB_POLICY_DELEGATION_PCR = 0x00000002
TSS_SECRET_LIFETIME_ALWAYS = 0x00000001
TSS_SECRET_LIFETIME_COUNTER = 0x00000002
TSS_SECRET_LIFETIME_TIMER = 0x00000003
TSS_TSPATTRIB_POLSECRET_LIFETIME_ALWAYS = TSS_SECRET_LIFETIME_ALWAYS
TSS_TSPATTRIB_POLSECRET_LIFETIME_COUNTER = TSS_SECRET_LIFETIME_COUNTER
TSS_TSPATTRIB_POLSECRET_LIFETIME_TIMER = TSS_SECRET_LIFETIME_TIMER
TSS_TSPATTRIB_POLICYSECRET_LIFETIME_ALWAYS = TSS_SECRET_LIFETIME_ALWAYS
TSS_TSPATTRIB_POLICYSECRET_LIFETIME_COUNTER = TSS_SECRET_LIFETIME_COUNTER
TSS_TSPATTRIB_POLICYSECRET_LIFETIME_TIMER = TSS_SECRET_LIFETIME_TIMER
TSS_TSPATTRIB_POLDEL_TYPE = 0x00000001
TSS_TSPATTRIB_POLDEL_INDEX = 0x00000002
TSS_TSPATTRIB_POLDEL_PER1 = 0x00000003
TSS_TSPATTRIB_POLDEL_PER2 = 0x00000004
TSS_TSPATTRIB_POLDEL_LABEL = 0x00000005
TSS_TSPATTRIB_POLDEL_FAMILYID = 0x00000006
TSS_TSPATTRIB_POLDEL_VERCOUNT = 0x00000007
TSS_TSPATTRIB_POLDEL_OWNERBLOB = 0x00000008
TSS_TSPATTRIB_POLDEL_KEYBLOB = 0x00000009
TSS_TSPATTRIB_POLDELPCR_LOCALITY = 0x00000001
TSS_TSPATTRIB_POLDELPCR_DIGESTATRELEASE = 0x00000002
TSS_TSPATTRIB_POLDELPCR_SELECTION = 0x00000003
TSS_DELEGATIONTYPE_NONE = 0x00000001
TSS_DELEGATIONTYPE_OWNER = 0x00000002
TSS_DELEGATIONTYPE_KEY = 0x00000003
TSS_SECRET_MODE_NONE = 0x00000800
TSS_SECRET_MODE_SHA1 = 0x00001000
TSS_SECRET_MODE_PLAIN = 0x00001800
TSS_SECRET_MODE_POPUP = 0x00002000
TSS_SECRET_MODE_CALLBACK = 0x00002800
TSS_TSPATTRIB_ENCDATA_BLOB = 0x00000008
TSS_TSPATTRIB_ENCDATA_PCR = 0x00000010
TSS_TSPATTRIB_ENCDATA_PCR_LONG = 0x00000018
TSS_TSPATTRIB_ENCDATA_SEAL = 0x00000020
TSS_TSPATTRIB_ENCDATABLOB_BLOB = 0x00000001
TSS_TSPATTRIB_ENCDATAPCR_DIGEST_ATCREATION = 0x00000002
TSS_TSPATTRIB_ENCDATAPCR_DIGEST_ATRELEASE = 0x00000003
TSS_TSPATTRIB_ENCDATAPCR_SELECTION = 0x00000004
TSS_TSPATTRIB_ENCDATAPCR_DIGEST_RELEASE = TSS_TSPATTRIB_ENCDATAPCR_DIGEST_ATRELEASE
TSS_TSPATTRIB_ENCDATAPCRLONG_LOCALITY_ATCREATION = 0x00000005
TSS_TSPATTRIB_ENCDATAPCRLONG_LOCALITY_ATRELEASE = 0x00000006
TSS_TSPATTRIB_ENCDATAPCRLONG_CREATION_SELECTION = 0x00000007
TSS_TSPATTRIB_ENCDATAPCRLONG_RELEASE_SELECTION = 0x00000008
TSS_TSPATTRIB_ENCDATAPCRLONG_DIGEST_ATCREATION = 0x00000009
TSS_TSPATTRIB_ENCDATAPCRLONG_DIGEST_ATRELEASE = 0x0000000A
TSS_TSPATTRIB_ENCDATASEAL_PROTECT_MODE = 0x00000001
TSS_TSPATTRIB_ENCDATASEAL_NOPROTECT = 0x00000000
TSS_TSPATTRIB_ENCDATASEAL_PROTECT = 0x00000001
TSS_TSPATTRIB_ENCDATASEAL_NO_PROTECT = TSS_TSPATTRIB_ENCDATASEAL_NOPROTECT
TSS_TSPATTRIB_NV_INDEX = 0x00000001
TSS_TSPATTRIB_NV_PERMISSIONS = 0x00000002
TSS_TSPATTRIB_NV_STATE = 0x00000003
TSS_TSPATTRIB_NV_DATASIZE = 0x00000004
TSS_TSPATTRIB_NV_PCR = 0x00000005
TSS_TSPATTRIB_NVSTATE_READSTCLEAR = 0x00100000
TSS_TSPATTRIB_NVSTATE_WRITESTCLEAR = 0x00200000
TSS_TSPATTRIB_NVSTATE_WRITEDEFINE = 0x00300000
TSS_TSPATTRIB_NVPCR_READPCRSELECTION = 0x01000000
TSS_TSPATTRIB_NVPCR_READDIGESTATRELEASE = 0x02000000
TSS_TSPATTRIB_NVPCR_READLOCALITYATRELEASE = 0x03000000
TSS_TSPATTRIB_NVPCR_WRITEPCRSELECTION = 0x04000000
TSS_TSPATTRIB_NVPCR_WRITEDIGESTATRELEASE = 0x05000000
TSS_TSPATTRIB_NVPCR_WRITELOCALITYATRELEASE = 0x06000000
TSS_NV_TPM = 0x80000000
TSS_NV_PLATFORM = 0x40000000
TSS_NV_USER = 0x20000000
TSS_NV_DEFINED = 0x10000000
TSS_NV_MASK_TPM = 0x80000000
TSS_NV_MASK_PLATFORM = 0x40000000
TSS_NV_MASK_USER = 0x20000000
TSS_NV_MASK_DEFINED = 0x10000000
TSS_NV_MASK_RESERVED = 0x0f000000
TSS_NV_MASK_PURVIEW = 0x00ff0000
TSS_NV_MASK_INDEX = 0x0000ffff
TSS_NV_INDEX_SESSIONS = 0x00011101
TSS_MIGATTRIB_MIGRATIONBLOB = 0x00000010
TSS_MIGATTRIB_MIGRATIONTICKET = 0x00000020
TSS_MIGATTRIB_AUTHORITY_DATA = 0x00000030
TSS_MIGATTRIB_MIG_AUTH_DATA = 0x00000040
TSS_MIGATTRIB_TICKET_DATA = 0x00000050
TSS_MIGATTRIB_PAYLOAD_TYPE = 0x00000060
TSS_MIGATTRIB_MIGRATION_XOR_BLOB = 0x00000101
TSS_MIGATTRIB_MIGRATION_REWRAPPED_BLOB = 0x00000102
TSS_MIGATTRIB_MIG_MSALIST_PUBKEY_BLOB = 0x00000103
TSS_MIGATTRIB_MIG_AUTHORITY_PUBKEY_BLOB = 0x00000104
TSS_MIGATTRIB_MIG_DESTINATION_PUBKEY_BLOB = 0x00000105
TSS_MIGATTRIB_MIG_SOURCE_PUBKEY_BLOB = 0x00000106
TSS_MIGATTRIB_MIG_REWRAPPED_BLOB = TSS_MIGATTRIB_MIGRATION_REWRAPPED_BLOB
TSS_MIGATTRIB_MIG_XOR_BLOB = TSS_MIGATTRIB_MIGRATION_XOR_BLOB
TSS_MIGATTRIB_AUTHORITY_DIGEST = 0x00000301
TSS_MIGATTRIB_AUTHORITY_APPROVAL_HMAC = 0x00000302
TSS_MIGATTRIB_AUTHORITY_MSALIST = 0x00000303
TSS_MIGATTRIB_MIG_AUTH_AUTHORITY_DIGEST = 0x00000401
TSS_MIGATTRIB_MIG_AUTH_DESTINATION_DIGEST = 0x00000402
TSS_MIGATTRIB_MIG_AUTH_SOURCE_DIGEST = 0x00000403
TSS_MIGATTRIB_TICKET_SIG_DIGEST = 0x00000501
TSS_MIGATTRIB_TICKET_SIG_VALUE = 0x00000502
TSS_MIGATTRIB_TICKET_SIG_TICKET = 0x00000503
TSS_MIGATTRIB_TICKET_RESTRICT_TICKET = 0x00000504
TSS_MIGATTRIB_PT_MIGRATE_RESTRICTED = 0x00000601
TSS_MIGATTRIB_PT_MIGRATE_EXTERNAL = 0x00000602
TSS_TSPATTRIB_HASH_IDENTIFIER = 0x00001000
TSS_TSPATTRIB_ALG_IDENTIFIER = 0x00002000
TSS_TSPATTRIB_PCRS_INFO = 0x00000001
TSS_TSPATTRIB_PCRSINFO_PCRSTRUCT = 0x00000001
TSS_TSPATTRIB_DELFAMILY_STATE = 0x00000001
TSS_TSPATTRIB_DELFAMILY_INFO = 0x00000002
TSS_TSPATTRIB_DELFAMILYSTATE_LOCKED = 0x00000001
TSS_TSPATTRIB_DELFAMILYSTATE_ENABLED = 0x00000002
TSS_TSPATTRIB_DELFAMILYINFO_LABEL = 0x00000003
TSS_TSPATTRIB_DELFAMILYINFO_VERCOUNT = 0x00000004
TSS_TSPATTRIB_DELFAMILYINFO_FAMILYID = 0x00000005
TSS_DELEGATE_INCREMENTVERIFICATIONCOUNT = 1
TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING = 1
TSS_TSPATTRIB_DAACRED_COMMIT = 0x00000001
TSS_TSPATTRIB_DAACRED_ATTRIB_GAMMAS = 0x00000002
TSS_TSPATTRIB_DAACRED_CREDENTIAL_BLOB = 0x00000003
TSS_TSPATTRIB_DAACRED_CALLBACK_SIGN = 0x00000004
TSS_TSPATTRIB_DAACRED_CALLBACK_VERIFYSIGNATURE = 0x00000005
TSS_TSPATTRIB_DAACOMMIT_NUMBER = 0x00000001
TSS_TSPATTRIB_DAACOMMIT_SELECTION = 0x00000002
TSS_TSPATTRIB_DAACOMMIT_COMMITMENTS = 0x00000003
TSS_TSPATTRIB_DAAATTRIBGAMMAS_BLOB = 0xffffffff
TSS_TSPATTRIB_DAAISSUERKEY_BLOB = 0x00000001
TSS_TSPATTRIB_DAAISSUERKEY_PUBKEY = 0x00000002
TSS_TSPATTRIB_DAAISSUERKEYBLOB_PUBLIC_KEY = 0x00000001
TSS_TSPATTRIB_DAAISSUERKEYBLOB_SECRET_KEY = 0x00000002
TSS_TSPATTRIB_DAAISSUERKEYBLOB_KEYBLOB = 0x00000003
TSS_TSPATTRIB_DAAISSUERKEYBLOB_PROOF = 0x00000004
TSS_TSPATTRIB_DAAISSUERKEYPUBKEY_NUM_ATTRIBS = 0x00000001
TSS_TSPATTRIB_DAAISSUERKEYPUBKEY_NUM_PLATFORM_ATTRIBS = 0x00000002
TSS_TSPATTRIB_DAAISSUERKEYPUBKEY_NUM_ISSUER_ATTRIBS = 0x00000003
TSS_TSPATTRIB_DAAARAKEY_BLOB = 0x00000001
TSS_TSPATTRIB_DAAARAKEYBLOB_PUBLIC_KEY = 0x00000001
TSS_TSPATTRIB_DAAARAKEYBLOB_SECRET_KEY = 0x00000002
TSS_TSPATTRIB_DAAARAKEYBLOB_KEYBLOB = 0x00000003
TSS_FLAG_DAA_PSEUDONYM_PLAIN = 0x00000000
TSS_FLAG_DAA_PSEUDONYM_ENCRYPTED = 0x00000001
TSS_TSPATTRIB_KEY_BLOB = 0x00000040
TSS_TSPATTRIB_KEY_INFO = 0x00000080
TSS_TSPATTRIB_KEY_UUID = 0x000000C0
TSS_TSPATTRIB_KEY_PCR = 0x00000100
TSS_TSPATTRIB_RSAKEY_INFO = 0x00000140
TSS_TSPATTRIB_KEY_REGISTER = 0x00000180
TSS_TSPATTRIB_KEY_PCR_LONG = 0x000001c0
TSS_TSPATTRIB_KEY_CONTROLBIT = 0x00000200
TSS_TSPATTRIB_KEY_CMKINFO = 0x00000400
TSS_TSPATTRIB_KEYBLOB_BLOB = 0x00000008
TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY = 0x00000010
TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY = 0x00000028
TSS_TSPATTRIB_KEYINFO_SIZE = 0x00000080
TSS_TSPATTRIB_KEYINFO_USAGE = 0x00000100
TSS_TSPATTRIB_KEYINFO_KEYFLAGS = 0x00000180
TSS_TSPATTRIB_KEYINFO_AUTHUSAGE = 0x00000200
TSS_TSPATTRIB_KEYINFO_ALGORITHM = 0x00000280
TSS_TSPATTRIB_KEYINFO_SIGSCHEME = 0x00000300
TSS_TSPATTRIB_KEYINFO_ENCSCHEME = 0x00000380
TSS_TSPATTRIB_KEYINFO_MIGRATABLE = 0x00000400
TSS_TSPATTRIB_KEYINFO_REDIRECTED = 0x00000480
TSS_TSPATTRIB_KEYINFO_VOLATILE = 0x00000500
TSS_TSPATTRIB_KEYINFO_AUTHDATAUSAGE = 0x00000580
TSS_TSPATTRIB_KEYINFO_VERSION = 0x00000600
TSS_TSPATTRIB_KEYINFO_CMK = 0x00000680
TSS_TSPATTRIB_KEYINFO_KEYSTRUCT = 0x00000700
TSS_TSPATTRIB_KEYCONTROL_OWNEREVICT = 0x00000780
TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT = 0x00001000
TSS_TSPATTRIB_KEYINFO_RSA_MODULUS = 0x00002000
TSS_TSPATTRIB_KEYINFO_RSA_KEYSIZE = 0x00003000
TSS_TSPATTRIB_KEYINFO_RSA_PRIMES = 0x00004000
TSS_TSPATTRIB_KEYPCR_DIGEST_ATCREATION = 0x00008000
TSS_TSPATTRIB_KEYPCR_DIGEST_ATRELEASE = 0x00010000
TSS_TSPATTRIB_KEYPCR_SELECTION = 0x00018000
TSS_TSPATTRIB_KEYREGISTER_USER = 0x02000000
TSS_TSPATTRIB_KEYREGISTER_SYSTEM = 0x04000000
TSS_TSPATTRIB_KEYREGISTER_NO = 0x06000000
TSS_TSPATTRIB_KEYPCRLONG_LOCALITY_ATCREATION = 0x00040000
TSS_TSPATTRIB_KEYPCRLONG_LOCALITY_ATRELEASE = 0x00080000
TSS_TSPATTRIB_KEYPCRLONG_CREATION_SELECTION = 0x000C0000
TSS_TSPATTRIB_KEYPCRLONG_RELEASE_SELECTION = 0x00100000
TSS_TSPATTRIB_KEYPCRLONG_DIGEST_ATCREATION = 0x00140000
TSS_TSPATTRIB_KEYPCRLONG_DIGEST_ATRELEASE = 0x00180000
TSS_TSPATTRIB_KEYINFO_CMK_MA_APPROVAL = 0x00000010
TSS_TSPATTRIB_KEYINFO_CMK_MA_DIGEST = 0x00000020
TSS_KEY_SIZEVAL_512BIT = 0x0200
TSS_KEY_SIZEVAL_1024BIT = 0x0400
TSS_KEY_SIZEVAL_2048BIT = 0x0800
TSS_KEY_SIZEVAL_4096BIT = 0x1000
TSS_KEY_SIZEVAL_8192BIT = 0x2000
TSS_KEY_SIZEVAL_16384BIT = 0x4000
TSS_KEYUSAGE_BIND = 0x00
TSS_KEYUSAGE_IDENTITY = 0x01
TSS_KEYUSAGE_LEGACY = 0x02
TSS_KEYUSAGE_SIGN = 0x03
TSS_KEYUSAGE_STORAGE = 0x04
TSS_KEYUSAGE_AUTHCHANGE = 0x05
TSS_KEYUSAGE_MIGRATE = 0x06
TSS_KEYFLAG_REDIRECTION = 0x00000001
TSS_KEYFLAG_MIGRATABLE = 0x00000002
TSS_KEYFLAG_VOLATILEKEY = 0x00000004
TSS_KEYFLAG_CERTIFIED_MIGRATABLE = 0x00000008
TSS_ALG_RSA = 0x20
TSS_ALG_DES = 0x21
TSS_ALG_3DES = 0x22
TSS_ALG_SHA = 0x23
TSS_ALG_HMAC = 0x24
TSS_ALG_AES128 = 0x25
TSS_ALG_AES192 = 0x26
TSS_ALG_AES256 = 0x27
TSS_ALG_XOR = 0x28
TSS_ALG_MGF1 = 0x29
TSS_ALG_AES = TSS_ALG_AES128
TSS_ALG_DEFAULT = 0xfe
TSS_ALG_DEFAULT_SIZE = 0xff
TSS_SS_NONE = 0x10
TSS_SS_RSASSAPKCS1V15_SHA1 = 0x11
TSS_SS_RSASSAPKCS1V15_DER = 0x12
TSS_SS_RSASSAPKCS1V15_INFO = 0x13
TSS_ES_NONE = 0x10
TSS_ES_RSAESPKCSV15 = 0x11
TSS_ES_RSAESOAEP_SHA1_MGF1 = 0x12
TSS_ES_SYM_CNT = 0x13
TSS_ES_SYM_OFB = 0x14
TSS_ES_SYM_CBC_PKCS5PAD = 0x15
TSS_PS_TYPE_USER = 1
TSS_PS_TYPE_SYSTEM = 2
TSS_MS_MIGRATE = 0x20
TSS_MS_REWRAP = 0x21
TSS_MS_MAINT = 0x22
TSS_MS_RESTRICT_MIGRATE = 0x23
TSS_MS_RESTRICT_APPROVE_DOUBLE = 0x24
TSS_MS_RESTRICT_MIGRATE_EXTERNAL = 0x25
TSS_KEYAUTH_AUTH_NEVER = 0x10
TSS_KEYAUTH_AUTH_ALWAYS = 0x11
TSS_KEYAUTH_AUTH_PRIV_USE_ONLY = 0x12
TSS_TPMSTATUS_DISABLEOWNERCLEAR = 0x00000001
TSS_TPMSTATUS_DISABLEFORCECLEAR = 0x00000002
TSS_TPMSTATUS_DISABLED = 0x00000003
TSS_TPMSTATUS_DEACTIVATED = 0x00000004
TSS_TPMSTATUS_OWNERSETDISABLE = 0x00000005
TSS_TPMSTATUS_SETOWNERINSTALL = 0x00000006
TSS_TPMSTATUS_DISABLEPUBEKREAD = 0x00000007
TSS_TPMSTATUS_ALLOWMAINTENANCE = 0x00000008
TSS_TPMSTATUS_PHYSPRES_LIFETIMELOCK = 0x00000009
TSS_TPMSTATUS_PHYSPRES_HWENABLE = 0x0000000A
TSS_TPMSTATUS_PHYSPRES_CMDENABLE = 0x0000000B
TSS_TPMSTATUS_PHYSPRES_LOCK = 0x0000000C
TSS_TPMSTATUS_PHYSPRESENCE = 0x0000000D
TSS_TPMSTATUS_PHYSICALDISABLE = 0x0000000E
TSS_TPMSTATUS_CEKP_USED = 0x0000000F
TSS_TPMSTATUS_PHYSICALSETDEACTIVATED = 0x00000010
TSS_TPMSTATUS_SETTEMPDEACTIVATED = 0x00000011
TSS_TPMSTATUS_POSTINITIALISE = 0x00000012
TSS_TPMSTATUS_TPMPOST = 0x00000013
TSS_TPMSTATUS_TPMPOSTLOCK = 0x00000014
TSS_TPMSTATUS_DISABLEPUBSRKREAD = 0x00000016
TSS_TPMSTATUS_MAINTENANCEUSED = 0x00000017
TSS_TPMSTATUS_OPERATORINSTALLED = 0x00000018
TSS_TPMSTATUS_OPERATOR_INSTALLED = TSS_TPMSTATUS_OPERATORINSTALLED
TSS_TPMSTATUS_FIPS = 0x00000019
TSS_TPMSTATUS_ENABLEREVOKEEK = 0x0000001A
TSS_TPMSTATUS_ENABLE_REVOKEEK = TSS_TPMSTATUS_ENABLEREVOKEEK
TSS_TPMSTATUS_NV_LOCK = 0x0000001B
TSS_TPMSTATUS_TPM_ESTABLISHED = 0x0000001C
TSS_TPMSTATUS_RESETLOCK = 0x0000001D
TSS_TPMSTATUS_DISABLE_FULL_DA_LOGIC_INFO = 0x0000001D
TSS_TPMCAP_ORD = 0x10
TSS_TPMCAP_ALG = 0x11
TSS_TPMCAP_FLAG = 0x12
TSS_TPMCAP_PROPERTY = 0x13
TSS_TPMCAP_VERSION = 0x14
TSS_TPMCAP_VERSION_VAL = 0x15
TSS_TPMCAP_NV_LIST = 0x16
TSS_TPMCAP_NV_INDEX = 0x17
TSS_TPMCAP_MFR = 0x18
TSS_TPMCAP_SYM_MODE = 0x19
TSS_TPMCAP_HANDLE = 0x1a
TSS_TPMCAP_TRANS_ES = 0x1b
TSS_TPMCAP_AUTH_ENCRYPT = 0x1c
TSS_TPMCAP_SET_PERM_FLAGS = 0x1d
TSS_TPMCAP_SET_VENDOR = 0x1e
TSS_TPMCAP_DA_LOGIC = 0x1f
TSS_TPMCAP_PROP_PCR = 0x10
TSS_TPMCAP_PROP_DIR = 0x11
TSS_TPMCAP_PROP_MANUFACTURER = 0x12
TSS_TPMCAP_PROP_SLOTS = 0x13
TSS_TPMCAP_PROP_KEYS = TSS_TPMCAP_PROP_SLOTS
TSS_TPMCAP_PROP_FAMILYROWS = 0x14
TSS_TPMCAP_PROP_DELEGATEROWS = 0x15
TSS_TPMCAP_PROP_OWNER = 0x16
TSS_TPMCAP_PROP_MAXKEYS = 0x18
TSS_TPMCAP_PROP_AUTHSESSIONS = 0x19
TSS_TPMCAP_PROP_MAXAUTHSESSIONS = 0x1a
TSS_TPMCAP_PROP_TRANSESSIONS = 0x1b
TSS_TPMCAP_PROP_MAXTRANSESSIONS = 0x1c
TSS_TPMCAP_PROP_SESSIONS = 0x1d
TSS_TPMCAP_PROP_MAXSESSIONS = 0x1e
TSS_TPMCAP_PROP_CONTEXTS = 0x1f
TSS_TPMCAP_PROP_MAXCONTEXTS = 0x20
TSS_TPMCAP_PROP_DAASESSIONS = 0x21
TSS_TPMCAP_PROP_MAXDAASESSIONS = 0x22
TSS_TPMCAP_PROP_DAA_INTERRUPT = 0x23
TSS_TPMCAP_PROP_COUNTERS = 0x24
TSS_TPMCAP_PROP_MAXCOUNTERS = 0x25
TSS_TPMCAP_PROP_ACTIVECOUNTER = 0x26
TSS_TPMCAP_PROP_MIN_COUNTER = 0x27
TSS_TPMCAP_PROP_TISTIMEOUTS = 0x28
TSS_TPMCAP_PROP_STARTUPEFFECTS = 0x29
TSS_TPMCAP_PROP_MAXCONTEXTCOUNTDIST = 0x2a
TSS_TPMCAP_PROP_CMKRESTRICTION = 0x2b
TSS_TPMCAP_PROP_DURATION = 0x2c
TSS_TPMCAP_PROP_MAXNVAVAILABLE = 0x2d
TSS_TPMCAP_PROP_INPUTBUFFERSIZE = 0x2e
TSS_TPMCAP_PROP_REVISION = 0x2f
TSS_TPMCAP_PROP_LOCALITIES_AVAIL = 0x32
TSS_RT_KEY = 0x00000010
TSS_RT_AUTH = 0x00000020
TSS_RT_TRANS = 0x00000030
TSS_RT_COUNTER = 0x00000040
TSS_TCSCAP_ALG = 0x00000001
TSS_TCSCAP_VERSION = 0x00000002
TSS_TCSCAP_CACHING = 0x00000003
TSS_TCSCAP_PERSSTORAGE = 0x00000004
TSS_TCSCAP_MANUFACTURER = 0x00000005
TSS_TCSCAP_PLATFORM_CLASS = 0x00000006
TSS_TCSCAP_TRANSPORT = 0x00000007
TSS_TCSCAP_PLATFORM_INFO = 0x00000008
TSS_TCSCAP_PROP_KEYCACHE = 0x00000100
TSS_TCSCAP_PROP_AUTHCACHE = 0x00000101
TSS_TCSCAP_PROP_MANUFACTURER_STR = 0x00000102
TSS_TCSCAP_PROP_MANUFACTURER_ID = 0x00000103
TSS_TCSCAP_PLATFORM_VERSION = 0x00001100
TSS_TCSCAP_PLATFORM_TYPE = 0x00001101
TSS_TCSCAP_TRANS_EXCLUSIVE = 0x00002100
TSS_TCSCAP_PROP_HOST_PLATFORM = 0x00003001
TSS_TCSCAP_PROP_ALL_PLATFORMS = 0x00003002
TSS_TSPCAP_ALG = 0x00000010
TSS_TSPCAP_VERSION = 0x00000011
TSS_TSPCAP_PERSSTORAGE = 0x00000012
TSS_TSPCAP_MANUFACTURER = 0x00000013
TSS_TSPCAP_RETURNVALUE_INFO = 0x00000015
TSS_TSPCAP_PLATFORM_INFO = 0x00000016
TSS_TSPCAP_PROP_MANUFACTURER_STR = 0x00000102
TSS_TSPCAP_PROP_MANUFACTURER_ID = 0x00000103
TSS_TSPCAP_PLATFORM_TYPE = 0x00000201
TSS_TSPCAP_PLATFORM_VERSION = 0x00000202
TSS_TSPCAP_PROP_RETURNVALUE_INFO = 0x00000201
TSS_EV_CODE_CERT = 0x00000001
TSS_EV_CODE_NOCERT = 0x00000002
TSS_EV_XML_CONFIG = 0x00000003
TSS_EV_NO_ACTION = 0x00000004
TSS_EV_SEPARATOR = 0x00000005
TSS_EV_ACTION = 0x00000006
TSS_EV_PLATFORM_SPECIFIC = 0x00000007
TSS_TSPCAP_RANDOMLIMIT = 0x00001000
TSS_PCRS_DIRECTION_CREATION = 1
TSS_PCRS_DIRECTION_RELEASE = 2
TSS_BLOB_STRUCT_VERSION = 0x01
TSS_BLOB_TYPE_KEY = 0x01
TSS_BLOB_TYPE_PUBKEY = 0x02
TSS_BLOB_TYPE_MIGKEY = 0x03
TSS_BLOB_TYPE_SEALEDDATA = 0x04
TSS_BLOB_TYPE_BOUNDDATA = 0x05
TSS_BLOB_TYPE_MIGTICKET = 0x06
TSS_BLOB_TYPE_PRIVATEKEY = 0x07
TSS_BLOB_TYPE_PRIVATEKEY_MOD1 = 0x08
TSS_BLOB_TYPE_RANDOM_XOR = 0x09
TSS_BLOB_TYPE_CERTIFY_INFO = 0x0A
TSS_BLOB_TYPE_KEY_1_2 = 0x0B
TSS_BLOB_TYPE_CERTIFY_INFO_2 = 0x0C
TSS_BLOB_TYPE_CMK_MIG_KEY = 0x0D
TSS_BLOB_TYPE_CMK_BYTE_STREAM = 0x0E
TSS_CMK_DELEGATE_SIGNING = 1 << 31
TSS_CMK_DELEGATE_STORAGE = 1 << 30
TSS_CMK_DELEGATE_BIND = 1 << 29
TSS_CMK_DELEGATE_LEGACY = 1 << 28
TSS_CMK_DELEGATE_MIGRATE = 1 << 27
TSS_DAA_LENGTH_N = 256
TSS_DAA_LENGTH_F = 13
TSS_DAA_LENGTH_E = 46
TSS_DAA_LENGTH_E_PRIME = 15
TSS_DAA_LENGTH_V = 317
TSS_DAA_LENGTH_SAFETY = 10
TSS_DAA_LENGTH_HASH = 20
TSS_DAA_LENGTH_S = 128
TSS_DAA_LENGTH_GAMMA = 204
TSS_DAA_LENGTH_RHO = 26
TSS_DAA_LENGTH_MFG1_GAMMA = 214
TSS_DAA_LENGTH_MGF1_AR = 25
TPM_ALG_RSA = 0x00000001
TPM_ALG_DES = 0x00000002
TPM_ALG_3DES = 0x00000003
TPM_ALG_SHA = 0x00000004
TPM_ALG_HMAC = 0x00000005
TPM_ALG_AES = 0x00000006
TPM_ALG_AES128 = TPM_ALG_AES
TPM_ALG_MGF1 = 0x00000007
TPM_ALG_AES192 = 0x00000008
TPM_ALG_AES256 = 0x00000009
TPM_ALG_XOR = 0x0000000A
TPM_SS_NONE = 0x0001
TPM_SS_RSASSAPKCS1v15_SHA1 = 0x0002
TPM_SS_RSASSAPKCS1v15_DER = 0x0003
TPM_SS_RSASSAPKCS1v15_INFO = 0x0004
TPM_ES_NONE = 0x0001
TPM_ES_RSAESPKCSv15 = 0x0002
TPM_ES_RSAESOAEP_SHA1_MGF1 = 0x0003
TPM_ES_SYM_CNT = 0x0004
TPM_ES_SYM_CTR = TPM_ES_SYM_CNT
TPM_ES_SYM_OFB = 0x0005
TPM_ES_SYM_CBC_PKCS5PAD = 0x00FF
)
// Log represents an entry from the TSS event log. Pcr is the register that
// was extended by the event. Eventtype is the type of the event. PcrValue
// is the value that was hashed into the TPM. Event is the raw event data.
type Log struct {
Pcr int32
Eventtype int32
PcrValue [20]byte
Event []byte
}
go-tspi-0.3.0/verification/ 0000775 0000000 0000000 00000000000 14067646345 0015575 5 ustar 00root root 0000000 0000000 go-tspi-0.3.0/verification/verification.go 0000664 0000000 0000000 00000075302 14067646345 0020615 0 ustar 00root root 0000000 0000000 // Copyright 2015 CoreOS, Inc.
//
// 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 verification
import (
"bytes"
"crypto"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"encoding/binary"
"encoding/pem"
"errors"
"fmt"
"math/big"
"github.com/google/certificate-transparency-go/x509"
"github.com/google/go-tspi/tspiconst"
)
func pad(plaintext []byte, bsize int) ([]byte, error) {
if bsize >= 256 {
return nil, errors.New("bsize must be < 256")
}
pad := bsize - (len(plaintext) % bsize)
if pad == 0 {
pad = bsize
}
for i := 0; i < pad; i++ {
plaintext = append(plaintext, byte(pad))
}
return plaintext, nil
}
// GenerateChallengeEx takes the EK (rsa.PublicKey), the public half of
// the AIK to be challenged and a secret. It then symmetrically encrypts the
// secret with a randomly generated AES key and Asymmetrically encrypts the
// AES key with the public half of the EK. These can then be provided to the
// TPM in order to ensure that the AIK is under the control of the TPM. It
// returns the asymmetrically and symmetrically encrypted data, along with
// any error.
func GenerateChallengeEx(pubkey *rsa.PublicKey, aikpub []byte, secret []byte) (asymenc []byte, symenc []byte, err error) {
aeskey := make([]byte, 16)
iv := make([]byte, 16)
_, err = rand.Read(aeskey)
if err != nil {
return nil, nil, err
}
_, err = rand.Read(iv)
if err != nil {
return nil, nil, err
}
asymplain := []byte{0x00, 0x00, 0x00, 0x06, 0x00, 0xff, 0x00, 0x10}
asymplain = append(asymplain, aeskey...)
hash := sha1.Sum(aikpub)
asymplain = append(asymplain, hash[:]...)
label := []byte{'T', 'C', 'P', 'A'}
asymenc, err = rsa.EncryptOAEP(sha1.New(), rand.Reader, pubkey, asymplain, label)
block, err := aes.NewCipher(aeskey)
if err != nil {
return nil, nil, err
}
cbc := cipher.NewCBCEncrypter(block, iv)
secret, err = pad(secret, len(iv))
if err != nil {
return nil, nil, err
}
symenc = make([]byte, len(secret))
cbc.CryptBlocks(symenc, secret)
symheader := new(bytes.Buffer)
err = binary.Write(symheader, binary.BigEndian, (uint32)(len(symenc)+len(iv)))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint32)(tspiconst.TPM_ALG_AES))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint16)(tspiconst.TPM_ES_SYM_CBC_PKCS5PAD))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint16)(tspiconst.TPM_SS_NONE))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint32)(12))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint32)(128))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint32)(len(iv)))
if err != nil {
return nil, nil, err
}
err = binary.Write(symheader, binary.BigEndian, (uint32)(0))
if err != nil {
return nil, nil, err
}
header := make([]byte, 28)
err = binary.Read(symheader, binary.BigEndian, &header)
header = append(header, iv...)
header = append(header, symenc...)
symenc = header
return asymenc, symenc, nil
}
// GenerateChallenge takes a copy of the EK certificate, the public half of
// the AIK to be challenged and a secret. It then symmetrically encrypts the
// secret with a randomly generated AES key and Asymmetrically encrypts the
// AES key with the public half of the EK. These can then be provided to the
// TPM in order to ensure that the AIK is under the control of the TPM. It
// returns the asymmetrically and symmetrically encrypted data, along with
// any error.
func GenerateChallenge(ekcert []byte, aikpub []byte, secret []byte) (asymenc []byte, symenc []byte, err error) {
/*
* Some EK certificates use RSAES-OAEP public keys.
* This is currently not supported by crypto/x509 but
* we are working with them to find a solution.
* https://github.com/golang/go/issues/30416
*/
cert, err := x509.ParseCertificate(ekcert)
if err != nil {
return nil, nil, fmt.Errorf("ParseCertificate failed: %v", err)
}
pubkey := cert.PublicKey.(*rsa.PublicKey)
return GenerateChallengeEx(pubkey, aikpub, secret)
}
// VerifyEKCert verifies that the provided EK certificate is signed by a
// trusted manufacturer.
func VerifyEKCert(ekcert []byte) error {
trustedCerts := map[string]string{
"STM1": `-----BEGIN CERTIFICATE-----
MIIDzDCCArSgAwIBAgIEAAAAATANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJD
SDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMRswGQYDVQQDExJTVE0g
VFBNIEVLIFJvb3QgQ0EwHhcNMDkwNzI4MDAwMDAwWhcNMjkxMjMxMDAwMDAwWjBV
MQswCQYDVQQGEwJDSDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMSYw
JAYDVQQDEx1TVE0gVFBNIEVLIEludGVybWVkaWF0ZSBDQSAwMTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJQYnWO8iw955vWqakWNr3YyazQnNzqV97+l
Qa+wUKMVY+lsyhAyOyXO31j4+clvsj6+JhNEwQtcnpkSc+TX60eZvLhgZPUgRVuK
B9w4GUVyg/db593QUmP8K41Is8E+l32CQdcVh9go0toqf/oS/za1TDFHEHLlB4dC
joKkfr3/hkGA9XJaoUopO2ELt4Otop12aw1BknoiTh1+YbzrZtAlIwK2TX99GW3S
IjaCi+fLoXyK2Fmx8vKnr9JfNL888xK9BQfhZzKmbKm/eLD1e1CFRs1B3z2gd3ax
pW5j1OIkSBMOIUeip5+7xvYo2gor5mxatB+rzSvrWup9AwIcymMCAwEAAaOBrjCB
qzAdBgNVHQ4EFgQU88kVdKbnc/8TvwxrrXp7Zc8ceCAwHwYDVR0jBBgwFoAUb+bF
bAe3bIsKgZKDXMtBHva00ScwRQYDVR0gAQH/BDswOTA3BgRVHSAAMC8wLQYIKwYB
BQUHAgEWIWh0dHA6Ly93d3cuc3QuY29tL1RQTS9yZXBvc2l0b3J5LzAOBgNVHQ8B
Af8EBAMCAAQwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsFAAOCAQEA
uZqViou3aZDGvaAn29gghOkj04SkEWViZR3dU3DGrA+5ZX+zr6kZduus3Hf0bVHT
I318PZGTml1wm6faDRomE8bI5xADWhPiCQ1Gf7cFPiqaPkq7mgdC6SGlQtRAfoP8
ISUJlih0UtsqBWGql4lpk5G6YmvAezguWmMR0/O5Cx5w8YKfXkwAhegGmMGIoJFO
oSzJrS7jK2GnGCuRG65OQVC5HiQY2fFF0JePLWG/D56djNxMbPNGTHF3+yBWg0DU
0xJKYKGFdjFcw0Wi0m2j49Pv3JD1f78c2Z3I/65pkklZGu4awnKQcHeGIbdYF0hQ
LtDSBV4DR9q5GVxSR9JPgQ==
-----END CERTIFICATE-----`,
"STM2": `-----BEGIN CERTIFICATE-----
MIIDzDCCArSgAwIBAgIEAAAAAzANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJD
SDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMRswGQYDVQQDExJTVE0g
VFBNIEVLIFJvb3QgQ0EwHhcNMTEwMTIxMDAwMDAwWhcNMjkxMjMxMDAwMDAwWjBV
MQswCQYDVQQGEwJDSDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0cm9uaWNzIE5WMSYw
JAYDVQQDEx1TVE0gVFBNIEVLIEludGVybWVkaWF0ZSBDQSAwMjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJO3ihn/uHgV3HrlPZpv8+1+xg9ccLf3pVXJ
oT5n8PHHixN6ZRBmf/Ng85/ODZzxnotC64WD8GHMLyQ0Cna3MJF+MGJZ5R5JkuJR
B4CtgTPwcTVZIsCuup0aDWnPzYqHwvfaiD2FD0aaxCnTKIjWU9OztTD2I61xW2LK
EY4Vde+W3C7WZgS5TpqkbhJzy2NJj6oSMDKklfI3X8jVf7bngMcCR3X3NcIo349I
Dt1r1GfwB+oWrhogZVnMFJKAoSYP8aQrLDVl7SQOAgTXz2IDD6bo1jga/8Kb72dD
h8D2qrkqWh7Hwdas3jqqbb9uiq6O2dJJY86FjffjXPo3jGlFjTsCAwEAAaOBrjCB
qzAdBgNVHQ4EFgQUVx+Aa0fM55v6NZR87Yi40QBa4J4wHwYDVR0jBBgwFoAUb+bF
bAe3bIsKgZKDXMtBHvaO0ScwRQYDVR0gAQH/BDswOTA3BgRVHSAAMC8wLQYIKwYB
BQUHAgEWIWh0dHA6Ly93d3cuc3QuY29tL1RQTS9yZXBvc2l0b3J5LzAOBgNVHQ8B
Af8EBAMCAAQwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsFAAOCAQEA
4gllWq44PFWcv0JgMPOtyXDQx30YB5vBpjS0in7f/Y/r+1Dd8q3EZwNOwYApe+Lp
/ldNqCXw4XzmO8ZCVWOdQdVOqHZuSOhe++Jn0S7M4z2/1PQ6EbRczGfw3dlX63Ec
cEnrn6YMcgPC63Q+ID53vbTS3gpeX/SGpngtVwnzpuJ5rBajqSQUo5jBTBtuGQpO
Ko6Eu7U6Ouz7BVgOSn0mLbfSRb77PjOLZ3+97gSiMmV0iofS7ufemYqA8sF7ZFv/
lM2eOe/eeS56Jw+IPsnEU0Tf8Tn9hnEig1KP8VByRTWAJgiEOgX2nTs5iJbyZeIZ
RUjDHQQ5onqhgjpfRsC95g==
-----END CERTIFICATE-----`,
"NTC1": `-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIGAK3jXfbVMA0GCSqGSIb3DQEBBQUAMFIxUDAcBgNVBAMT
FU5UQyBUUE0gRUsgUm9vdCBDQSAwMTAlBgNVBAoTHk51dm90b24gVGVjaG5vbG9n
eSBDb3Jwb3JhdGlvbjAJBgNVBAYTAlRXMB4XDTEyMDcxMTE2MjkzMFoXDTMyMDcx
MTE2MjkzMFowUjFQMBwGA1UEAxMVTlRDIFRQTSBFSyBSb290IENBIDAxMCUGA1UE
ChMeTnV2b3RvbiBUZWNobm9sb2d5IENvcnBvcmF0aW9uMAkGA1UEBhMCVFcwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDoNqxhtD4yUtXhqKQGGZemoKJy
uj1RnWvmNgzItLeejNU8B6fOnpMQyoS4K72tMhhFRK2jV9RYzyJMSjEwyX0ASTO1
2yMti2UJQS60d36eGwk8WLgrFnnITlemshi01h9t1MOmay3TO1LLH/3/VDKJ+jbd
cbfIO2bBquN8r3/ojYUaNSPj6pK1mmsMoJXF4dGRSEwb/4ozBIw5dugm1MEq4Zj3
GZ0YPg5wyLRugQbt7DkUOX4FGuK5p/C0u5zX8u33EGTrDrRz3ye3zO+aAY1xXF/m
qwEqgxX5M8f0/DXTTO/CfeIksuPeOzujFtXfi5Cy64eeIZ0nAUG3jbtnGjoFAgMB
AAGjJjAkMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqG
SIb3DQEBBQUAA4IBAQBBQznOPJAsD4Yvyt/hXtVJSgBX/+rRfoaqbdt3UMbUPJYi
pUoTUgaTx02DVRwommO+hLx7CS++1F2zorWC8qQyvNbg7iffQbbjWitt8NPE6kCr
q0Y5g7M/LkQDd5N3cFfC15uFJOtlj+A2DGzir8dlXU/0qNq9dBFbi+y+Y3rAT+wK
fktmN82UT861wTUzDvnXO+v7H5DYXjUU8kejPW6q+GgsccIbVTOdHNNWbMrcD9yf
oS91nMZ/+/n7IfFWXNN82qERsrvOFCDsbIzUOR30N0IP++oqGfwAbKFfCOCFUz6j
jpXUdJlh22tp12UMsreibmi5bsWYBgybwSbRgvzE
-----END CERTIFICATE-----`,
"NTC2": `-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIGAPadBmPZMA0GCSqGSIb3DQEBBQUAMFIxUDAcBgNVBAMT
FU5UQyBUUE0gRUsgUm9vdCBDQSAwMjAlBgNVBAoTHk51dm90b24gVGVjaG5vbG9n
eSBDb3Jwb3JhdGlvbjAJBgNVBAYTAlRXMB4XDTEyMDcxMTE2MzMyNFoXDTMyMDcx
MTE2MzMyNFowUjFQMBwGA1UEAxMVTlRDIFRQTSBFSyBSb290IENBIDAyMCUGA1UE
ChMeTnV2b3RvbiBUZWNobm9sb2d5IENvcnBvcmF0aW9uMAkGA1UEBhMCVFcwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSagWxaANT1YA2YUSN7sq7yzOT
1ymbIM+WijhE5AGcLwLFoJ9fmaQrYL6fAW2EW/Q3yu97Q9Ysr8yYZ2XCCfxfseEr
Vs80an8Nk6LkTDz8+0Hm0Cct0klvNUAZEIvWpmgHZMvGijXyOcp4z494d8B28Ynb
I7x0JMXZZQQKQi+WfuHtntF+2osYScweocipPrGeONLKU9sngWZ2vnnvw1SBneTa
irxq0Q0SD6Bx9jtxvdf87euk8JzfPhX8jp8GEeAjmLwGR+tnOQrDmczGNmp7YYNN
R+Q7NZVoYWHw5jaoZnNxbouWUXZZxFqDsB/ndCKWtsIzRYPuWcqrFcmUN4SVAgMB
AAGjJjAkMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqG
SIb3DQEBBQUAA4IBAQAIkdDSErzPLPYrVthw4lKjW4tRYelUicMPEHKjQeVUAAS5
y9XTzB4DWISDAFsgtQjqHJj0xCG+vpY0Rmn2FCO/0YpP+YBQkdbJOsiyXCdFy9e4
gGjQ24gw1B+rr84+pkI51y952NYBdoQDeb7diPe+24U94f//DYt/JQ8cJua4alr3
2Pohhh5TxCXXfU2EHt67KyqBSxCSy9m4OkCOGLHL2X5nQIdXVj178mw6DSAwyhwR
n3uJo5MvUEoQTFZJKGSXfab619mIgzEr+YHsIQToqf44VfDMDdM+MFiXQ3a5fLii
hEKQ9DhBPtpHAbhFA4jhCiG9HA8FdEplJ+M4uxNz
-----END CERTIFICATE-----`,
"IFX1": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIEMV64bDANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0wNTEwMjAxMzQ3NDNaFw0yNTEwMjAxMzQ3NDNaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALftPhYN
t4rE+JnU/XOPICbOBLvfo6iA7nuq7zf4DzsAWBdsZEdFJQfaK331ihG3IpQnlQ2i
YtDim289265f0J4OkPFpKeFU27CsfozVaNUm6UR/uzwA8ncxFc3iZLRMRNLru/Al
VG053ULVDQMVx2iwwbBSAYO9pGiGbk1iMmuZaSErMdb9v0KRUyZM7yABiyDlM3cz
UQX5vLWV0uWqxdGoHwNva5u3ynP9UxPTZWHZOHE6+14rMzpobs6Ww2RR8BgF96rh
4rRAZEl8BXhwiQq4STvUXkfvdpWH4lzsGcDDtrB6Nt3KvVNvsKz+b07Dk+Xzt+EH
NTf3Byk2HlvX+scCAwEAAaOCATswggE3MB0GA1UdDgQWBBQ4k8292HPEIzMV4bE7
qWoNI8wQxzAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBABJ1+Ap3rNlxZ0FW0aIgdzktbNHlvXWNxFdYIBbM
OKjmbOos0Y4O60eKPu259XmMItCUmtbzF3oKYXq6ybARUT2Lm+JsseMF5VgikSlU
BJALqpKVjwAds81OtmnIQe2LSu4xcTSavpsL4f52cUAu/maMhtSgN9mq5roYptq9
DnSSDZrX4uYiMPl//rBaNDBflhJ727j8xo9CCohF3yQUoQm7coUgbRMzyO64yMIO
3fhb+Vuc7sNwrMOz3VJN14C3JMoGgXy0c57IP/kD5zGRvljKEvrRC2I147+fPeLS
DueRMS6lblvRKiZgmGAg7YaKOkOaEmVDMQ+fTo2Po7hI5wc=
-----END CERTIFICATE-----`,
"IFX2": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIEaItIgTANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0wNjEyMjExMDM0MDBaFw0yNjEyMjExMDM0MDBaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK6KnP5R
8ppq9TtPu3mAs3AFxdWhzK5ks+BixGR6mpzyXG64Bjl4xzBXeBIVtlBZXYvIAJ5s
eCTEEsnZc9eKNJeFLdmXQ/siRrTeonyxoS4aL1mVEQebLUz2gN9J6j1ewly+OvGk
jEYouGCzA+fARzLeRIrhuhBI0kUChbH7VM8FngJsbT4xKB3EJ6Wttma25VSimkAr
SPS6dzUDRS1OFCWtAtHJW6YjBnA4wgR8WfpXsnjeNpwEEB+JciWu1VAueLNI+Kis
RiferCfsgWRvHkR6RQf04h+FlhnYHJnf1ktqcEi1oYAjLsbYOAwqyoU1Pev9cS28
EA6FTJcxjuHhH9ECAwEAAaOCATswggE3MB0GA1UdDgQWBBRDMlr1UAQGVIkwzamm
fceAZ7l4ATAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBAIZAaYGzf9AYv6DqoUNx6wdpayhCeX75/IHuFQ/d
gLzat9Vd6qNKdAByskpOjpE0KRauEzD/BhTtkEJDazPSmVP1QxAPjqGaD+JjqhS/
Q6aY+1PSDi2zRIDA66V2yFJDcUBTtShbdTg144YSkVSY5UCKhQrsdg8yAbs7saAB
LHzVebTXffjmkTk5GZk26d/AZQRjfssta1N/TWhWTfuZtwYvjZmgDPeCfr6AOPLr
pVJz+ntzUKGpQ+5mwDJXMZ0qeiFIgXUlU0D+lfuajc/x9rgix9cM+o7amgDlRi1T
55Uu2vzUQ9jLUaISFaTTMag+quBDhx8BDVu+igLp5hvBtxQ=
-----END CERTIFICATE-----`,
"IFX3": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIEH7fYljANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0wNzA0MTMxNjQ0MjRaFw0yNzA0MTMxNjQ0MjRaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJWdPAuH
z/p1tIwB1QXlPD/PjedZ4uBZdwPH5tI3Uve0TzbR/mO5clx/loWn7nZ5cHkH1nhB
R67JEFY0a9GithPfITh0XRxPcisLBE/SoqZ90KHFaS+N6SwOpdCP0GlUg1OesKCF
79Z6fXrkTZsVpPqdawdZK+oUsDO9z9U6xqV7bwsS75Y+QiHsm6UTgAkSNQnuFMP3
NqQyDi/BaWaYRGQ6K8pM7Y7e1h21z/+5X7LncZXU8hgpYpu2zQPg96IkYboVUKL4
00snaPcOvfagsBUGlBltNfz7geaSuWTCdwEiwlkCYZqCtbkAj5FiStajrzP72BfT
2fshIv+5eF7Qp5ECAwEAAaOCATswggE3MB0GA1UdDgQWBBTGyypNtylL6RFyT1BB
MQtMQvibsjAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBAGN1bkh4J90DGcOPP2BlwE6ejJ0iDKf1zF+7CLu5
WS5K4dvuzsWUoQ5eplUt1LrIlorLr46mLokZD0RTG8t49Rcw4AvxMgWk7oYk69q2
0MGwXwgZ5OQypHaPwslmddLcX+RyEvjrdGpQx3E/87ZrQP8OKnmqI3pBlB8QwCGL
SV9AERaGDpzIHoObLlUjgHuD6aFekPfeIu1xbN25oZCWmqFVIhkKxWE1Xu+qqHIA
dnCFhoIWH3ie9OsJh/iDRaANYYGyplIibDx1FJA8fqiBiBBKUlPoJvbqmZs4meMd
OoeOuCvQ7op28UtaoV6H6BSYmN5dOgW7r1lX2Re0nd84NGE=
-----END CERTIFICATE-----`,
"IFX4": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIEDhD4wDANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0wNzEyMDMxMzA3NTVaFw0yNzEyMDMxMzA3NTVaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN3UBmDk
jJzzJ+WCgrq4tILtE9KJPMGHwvCsbJOlo7eHiEb8JQzGK1prkPQ3dowFRXPnqONP
WUa36/J3R32xgvuZHqAdliZCt8IUb9qYhDenuXo1SSqJ8LWp30QIJ0vnkaQ2TCkO
bveZZR3hK2OZKRTkFaV/iy2RH+Qs4JAe3diD8mlIu2gXAXnKJSkrzW6gbMzrlTOi
RCuGcatpy7Hfmodbz/0Trbuwtc3dyJZ3Ko1z9bz2Oirjh93RrmYjbtL0HhkAjMOR
83GLrzwUddSqmxtXXX8j5i+/gmE3AO71swOIESdGugxaKUzJ1jTqWKMZcx0E6BFI
lDIfKk0fJlSxHfECAwEAAaOCATswggE3MB0GA1UdDgQWBBSIs8E/YQXRBCKfWsDr
SZVkrNRzvTAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBAFtqClQNBLOzcGZUpsBqlz3frzM45iiBpxosG1Re
IgoAgtIBEtl609TG51tmpm294KqpfKZVO+xNzovm8k/heGb0jmYf+q1ggrk2qT4v
Qy2jgE0jbP/P8WWq8NHC13uMcBUGPaka7yofEDDwz7TcduQyJVfG2pd1vflnzP0+
iiJpfCk3CAQQnb+B7zsOp7jHNwpvHP+FhNwZaikaa0OdR/ML9da1sOOW3oJSTEjW
SMLuhaZHtcVgitvtOVvCI/aq47rNJku3xQ7c/s8FHnFzQQ+Q4TExbP20SrqQIlL/
9sFAb7/nKYNauusakiF3pfvMrJOJigNfJyIcWaGfyyQtVVI=
-----END CERTIFICATE-----`,
"IFX5": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIEVuRoqzANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0wOTEyMTExMDM4NDJaFw0yOTEyMTExMDM4NDJaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL79zMCO
bjkg7gCWEuyGO49CisF/QrGoz9adW1FBuSW8U9IOlvWXNsvoasC1mhrsfkRRojuU
mWifxxxcVfOI9v1SbRfJ+i6lG21IcVe6ywLJdDliT+3vzvrb/2hU/XjCCMDWb/Pw
aZslV5iL4QEiKxvRIiWMYHW0MkkL7mzRBDVN/Vz3ZiL5Lpq7awiKuX9OXpS2a1wf
qSGAlm2TxjU884q9Ky85JJugn0Q/C3dc8aaFPKLHlRs6rIvN1l0LwB1b5EWPzTPJ
d9EhRPFJOAbJS66nSgX06Fl7eWB71ow6w/25otLQCbpy6OrF8wBVMtPMHqFb1c32
PaaNzpCBnIU7vaMCAwEAAaOCATswggE3MB0GA1UdDgQWBBS7z3zBhCExZtq1vlOo
cBTd00jYzDAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBAHomNJtmFNtRJI2+s6ZwdzCTHXXIcR/T+N/lfPbE
hIUG4Kg+3uQMP7zBi22m3I3Kk9SXsjLqV5mnsQUGMGlF7jw5W5Q+d6NSJz4taw9D
2DsiUxE/i5vrjWiUaWxv2Eckd4MUexe5Qz8YSh4FPqLB8FZnAlgx2kfdzRIUjkMq
EgFK8ZRSUjXdczvsud68YPVMIZTxK0L8POGJ6RYiDrjTelprfZ4pKKZ79XwxwAIo
pG6emUEf+doRT0KoHoCHr9vvWCWKhojqlQ6jflPZcEsNBMbq5KHVN77vOU58OKx1
56v3EaqrZenVFt8+n6h2NzhOmg2quQXIr0V9jEg8GAMehDs=
-----END CERTIFICATE-----`,
"IFX8": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIEfGoY6jANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0xMjA3MTcwOTI0NTJaFw0zMDEwMTgyMzU5NTlaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAwODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOJaIJu6
r/betrMgWJ/JZ5j8ytoAA9RWq0cw7+W0e5L2kDLJMM288wYT+iEbfwx6sWSLAl7q
okXYDtTB9MFNhQ5ZWFLslFXbYigtXJxwANcSdPISTF1Czn6LLi1fu1EHddwCXFC8
xaX0iGgQ9pZklvAy2ijK9BPHquWisisEiWZNRT9dCVylzOR3+p2YOC3ZrRmg7Bj+
DkC7dltTTO6dPR+LNOFe01pJlpZdF4YHcu4EC10gRu0quZz1LtDZWFKezK7rg5Rj
LSAJbKOsGXjl6hQXMtADEX9Vlz1vItD21OYCNRsu6VdipiL0bl0aAio4BV3GMyjk
0gHnQwCk9k/YPU8CAwEAAaOCATswggE3MB0GA1UdDgQWBBRMS01kiQjkW/5aENNj
h6aIrsHPeDAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBALMiDyQ9WKH/eTI84Mk8KYk+TXXEwf+fhgeCvxOQ
G0FTSmOpJaNIzxWXr/gDbY3dO0ODjWRKYvhimZUuV+ckMA+wZX2C6o8g5njpWIOH
pSAa+W35ijArh0Zt3MASJ46avd+fnQGTdzT0hK46gx6n2KixLvaZsR3JtuwUFYlQ
wzmz/UsbBNEoPiR8p5E0Zf5GEGiTqkmBVYyS6XA34axpMMRHy0wI7AGs0gVihwUM
rr0iWOu+GAcrm11lcYzqJvuEkfenAF62ufA2Ktv+Ut2xiRC0jUIp73CeplAJsqBr
camV3pJn3qYPI5c1njMRYnoRFWQbrOR5ADWDQLFQPYRrJmg=
-----END CERTIFICATE-----`,
"IFX15": `-----BEGIN CERTIFICATE-----
MIIEnzCCA4egAwIBAgIER3V5aDANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJE
RTEQMA4GA1UECBMHQmF2YXJpYTEhMB8GA1UEChMYSW5maW5lb24gVGVjaG5vbG9n
aWVzIEFHMQwwCgYDVQQLEwNBSU0xGzAZBgNVBAMTEklGWCBUUE0gRUsgUm9vdCBD
QTAeFw0xMjExMTQxNDQzMzRaFw0zMDEwMTgyMzU5NTlaMHcxCzAJBgNVBAYTAkRF
MQ8wDQYDVQQIEwZTYXhvbnkxITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2ll
cyBBRzEMMAoGA1UECxMDQUlNMSYwJAYDVQQDEx1JRlggVFBNIEVLIEludGVybWVk
aWF0ZSBDQSAxNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKS6pgcg
OQWSozVbMkdf9jZkpGdT4U735zs0skfpjoKK2CgpLMO/+oGKbObm/DQPRQO/oxvq
jJNBKz55QBgKd+MoQ6t+2J8mcQ91Nfwqnm1C4r+c4zezJ1Utk/KIYNqpFDAzefBA
/lK8IxQ6kmzxcIFE4skaFsSgkearSZGG6sA9A51yxwvs8yUrQF51ICEUM7wDb4cM
53utaFdm6p6m9UZGSmmrdTiemOkuuwtl8IUQXfuk9lFyQsACBTM95Hrts0IzI6hX
QeTwSL4JqyEnKP9vbtT4eXzWNycqSYBf0+Uo/HHZo9WuVDUaA4I9zcmD0qCvSOT0
NAj4ifJ7SPGInU0CAwEAAaOCATswggE3MB0GA1UdDgQWBBR4pAnEV95pJvbfQsYR
TrflaptW5zAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADBYBgNV
HSABAf8ETjBMMEoGC2CGSAGG+EUBBy8BMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93
d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvaW5kZXguaHRtbDCBlwYDVR0jBIGP
MIGMgBRW65FEhWPWcrOu1EWWC/eUDlRCpqFxpG8wbTELMAkGA1UEBhMCREUxEDAO
BgNVBAgTB0JhdmFyaWExITAfBgNVBAoTGEluZmluZW9uIFRlY2hub2xvZ2llcyBB
RzEMMAoGA1UECxMDQUlNMRswGQYDVQQDExJJRlggVFBNIEVLIFJvb3QgQ0GCAQMw
DQYJKoZIhvcNAQEFBQADggEBAAnZDdJZs5QgAXnl0Jo5sCqktZcwcK+V1+uhsqrT
Z7OJ9Ze1YJ9XB14KxRfmck7Erl5HVc6PtUcLnR0tuJKKKqm7dTe4sQEFYd5usjrW
KSG6y7BOH7AdonocILY9OIxuNwxMAqhK8LIjkkRCeOWSvCqLnaLtrP52C0fBkTTM
SWX7YnsutXEpwhro3Qsnm9hL9s3s/WoIuNKUcLFH/qWKztpxXnF0zip73gcZbwEy
1GPQQpYnxFJ2R2ab2RHlO+3Uf3FDxn+eRLXNl95ZZ6GE4OIIpKEg2urIiig0HmGA
ijO6JfJxT30H9QNsx78sjYs7pOfMw6DfiqJ8Fx82GcCUOyM=
-----END CERTIFICATE-----`,
}
trustedKeys := map[string]string{
"ATM1": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5a+4yXtubUnGJPz7ZVjW
spGhe5Tr9BhrWQ9QOfDoVlkmi+tg2Gqc9qA9R39WhiiEmKuQ3+4XIvO+XFFrVCv+
8YuEnBIIu46FEX1LBG7LnUJbkgAV0pzHMWOghLhDIGcGg/6kO9fH+7KcwfwNah+Z
Lkfbfis3cm09RlOG8RSq8LyK8Zc07QH2M7L/8PFnRRQ5MnAgW7vuk8h/M62TTy+y
DVuWl/jnh3vrKgVMoOyL/iM3EdFHIV+r/lJOI/HRAlkieCRGiJ1kJI4tQpUXiL+t
K2iB1yAxnqcSQzWWxlNuu6sAUV2tI+qMVM2o6eT1f/MM7+b4nmyuBrdOIO5dvTek
7wIDAQAB
-----END PUBLIC KEY-----`,
"ATM10": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1HEeCn82r8Vrg64howvt
s/2Yj5yuXhEv7FwUaISo7rYFnAbstyMVGNsL24reRW7aiyj65iHEojx1Car3Jlu8
hYfTqiagFmEK/qe8erEatwg5jFQ0GdK3a9Tw7nhYZjjpe98sRjL/DQlI5NiKClPF
4ZNqI418MGmzmPN/QNxRnKJAr5LTE8FZCMShm5V9ege72oLj4VfPuz29fQLBZWJA
2+NUy6gCpcUShejGfm9DTGBk0m3wruqyXuzKzJ4U0Xo5nTqp7ZV/JLbSWnTJxs72
hZ4D1nbi0paPQgcK5FYbIwQ1WuEpN5QMfilsAZFbokQnQa+jX2Rzleoa0mURVEnG
TQIDAQAB
-----END PUBLIC KEY-----`,
"ATM11": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqrS1Ei1VvLxVYWNv/s35
aYmHa5MOnvQybgW/i1XuINZuPQqYNw02wrWRA5eft2ts+FkJDvbz6edtqH30Cjx+
pmE9OvotY7O7rboruz2W2PpcQ0/inLUixNiq/A8giKRWJaTNsiF6VLNEWEe5sf3r
e6+C/ZQUfwupM56bU0JrIMxEgp8SCFguQsNwcq2txtr1ujgX4PN6DOet6BcrTpsY
vxKhQPbL/Tfl/kMqYVzqqyrBGgkg8+2FRxO6bVSJCwryrA37ZwkgJl3k/qibTFzw
JVfJnGaT57L/TUVJRwADtVN+oJFcQamR7N6VIuohx7fp7U8t8nrKhZpIwK405hLE
1wIDAQAB
-----END PUBLIC KEY-----`,
"ATM12": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1R4fVBbUI7tsaRuS0VvH
TiouZ7L/HAokHIsozeLKamistnoCNKMyz40pwGenK8l0XnvJveoAlT+3tbKmmeo7
iR1QP28shN8ggnObHZpBN2cPiySh0A8uYIEXY3sJMrNZ/h2MMbjYD2nUyreVpuj+
mytSbvmB1eqcj9p4JBY1aqwXBrm0DqxZXJsVNBkjJ7c9kFy3ze8yccTFKx/wXe7v
PHgoWKA7RLtM2i/ppJdQgT/IubOrhZTyWPpvLQDpNf0p/SDmByw3/RzinPFlxUmA
eBzvTDwM7jEsZIUQGDZIBhifK45VLLrQiDTTOL8eVw9D8H0zn8AJu7cF9w9oYQj6
fQIDAQAB
-----END PUBLIC KEY-----`,
"ATM13": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSvUzUQRjD3KyZMJu5CZ
sHVLqAN0mBT86nivjCV+RhHsR0uSU110NKjb2IHXM3fYaJlgvZRTAQJ3c8jPc0bV
tC0+521QKKt86OLi0+nrNT2QzLtrJgx6eRoYiu9se2F0u/zB+PHQ0R8qVOI1xw0W
FVK2w2+mRT3WN4Udp0Rn6LKPRXCq59JPfuD7hNBVmwp9uzj2TLp8ljMRSbChRjek
u9H4G+b2qa4wf2g9R5/Eqq5cMwYsD4357cuhlfqWQxD61J93ro2Hf5+30JrZF2yo
/TX5ocdQqnvLeape1KZGTDrikNXD9eIhR53yT4aBAK/RB8scsbwjn5tnoIBO0GAE
wwIDAQAB
-----END PUBLIC KEY-----`,
"ATM2": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6e/oMMyv7NPlNKo9A7ls
wJDkE14LZGSsKiRyzyJe2qHCoBwsZEq3QV2w4ducngcOysRaczDd8Cku9Z332dbi
9Tq6RZapk/eL7mcBF/XBNu7Wft3PDRTzs8gpM3xFHo59+OAjeax3TE8yR6Phiipp
42uI9f184vQsgwzEWNz6kMUP5mwe3Hm9y8RlTzrpJAtVtW9w7LmoSeOHHgzsEGG9
q5F2PkY6X0Ft9eDQaIOlTofkSHzvG2VLv8MJINMjnXrPnvF8dqG38lzAIvDfJKKx
E5MjY2aoFc1dfISQDv4sYx02b6jwfDl8pFCrwCzH7cWmIE0hD2BV2LpurURTi+kk
MQIDAQAB
-----END PUBLIC KEY-----`,
"ATM3": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmFAUATJ/8xIeuFW0aKNZ
cwCtDLDOQoGIez+sg64EmJ+rEKNHfPQj7ee3UxiARWoLvmrMwMZFHXVuHb6Q6QUB
H2OmUZfhcBXm94ZbXrFQyDxosR3lU+JZu5JK0X76kZAQtiBI2/UkJMt0xRUm1P7p
InKnqk9HYw2HpwrCYZII78R2N8bfGJAXOpz1oOpI7jVHewtJY/gun1jgXuOwNW+1
ouDaUrB/8t9m0lvsoeqduq0Nhvl4AL6kxVFp4sSX3gFuSORcbFP4hu7UMJy6g59d
bsgpulbltd2+HDqxEa4VPOe3IlC4iUso091vq+V49ThYOZ0TXFjk1dNdcTFuK2O8
kQIDAQAB
-----END PUBLIC KEY-----`,
"ATM4": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxtl1salu/2SXeqCGMtac
0GMCqx6Qeh4KtrviPfGVdObksuyGRPPuaW25/oYNGLlf2x/kDlknB2eZFMiW8otK
XV+xO50uFcxoTHXZ1wnMD8x6CgM0z0j3DQ5d0eu5sRRDd7GHYEpuvMj0x8pgkZk+
C+Ux2hWlj8xEiEDH8q5wyP5AX92GkpoUAL0e4vUV7/cCEBcsLOs8Oq6rKzmig82k
sDiL/Tn/8TtsSmUAwT/FzM/gi79x0D1hHtXyLOFPDIrOy3d3cz5QMOSSLDHGjmoa
DBF0+rcBRJCCU2iBtfIMBevJO1IBUmj/EgerHWWaf5pNNJAL62eAeeaWKm5OaX6b
VQIDAQAB
-----END PUBLIC KEY-----`,
"ATM5": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqg1FjhOQ/GsqgUL+WSBc
fYr3hkxxl1EBaCIqiolc1R5TmZabaHoCUIJmhwXfFGhFvhZrI0AcEqIYANLgY0ri
vn4h6vV+rrwtxM1X7X8hmT+AdvxL2p9lOCp7XNpQ2Rw+o/2JhuBSUv+opW7K6wPu
mwUpy4gL+dAozZyBjan5Co9sP5Yh3kdG3+ezRsfxf3CnS76NhjHglK9AWUdM1c6m
FGqTP+fU9ySTpoabrnDUzIcedu5OsMZa5L1LeLKHrqrbM3b995aU9RPrIQoO3x+B
Sau9Ab0d614zpD0TeWwjBT7Y5rIg14bIx7DiA+4kGRE5fHZtpdSWpgJmlkcObSSd
vQIDAQAB
-----END PUBLIC KEY-----`,
"ATM6": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw9s9ykpgzH1Birz8JVmH
c/jXNSaFsDQYM9hcS3513P7arS+r/musmUqfdybY/GQ8+YqAA6IZq+xlGZ7WUEmx
vo/Hlnm/FQj3epZGD3ruApm+8dLV4Hvs4RjZCS8cfpkRZygh+nRdrZ3aAwZRjQbh
vl8mAJOQ2Rp9ANaZMzYjre7adkuqIFDa83nKgn4XkMIft+MthOvcMYmZtSL64gvA
NZ7PiryB2cMhS+0yAMGK/Oqm0ELIRk8wqAR/l3txRVxoQEqA9fBk2bvGNiWva92c
hxCLpEX9+CcZWvUeH6Up5a2EDxw8BgxE0L6sqjINWn2uN0x7jlKysg+XEyo7qUpM
RQIDAQAB
-----END PUBLIC KEY-----`,
"ATM7": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlYRfDD3bMJB7w6Fl+Kez
oIaEkzz+2VCeF8v3ohsNnSKCgcx8uk7Seyp50bEtLB6vOzwgcM5WjFItKyYLZaHt
P43q3iHsvISjAGNcYGcQ3NrM4ia6pc2geVraupldPTdQFOQjwd+0P/Q2/RMbWY6g
+sbjIDtItEc1vhf6bI3TinT+bGxxXdR9B6qWgLNc/H31wsBNN2nPv1K4wE8MWfAV
7hcK2NoIc1zGEY+IiWPtXSu48zmvS2lxKWWYuiHBwCt5ns/U7M8XSjkaj7SbhD02
yKwiMavu7SMAceSWWMBuhjgm9/zfMAPKO9weQixVCeuXspByefsekPuk5ohbWOS/
bwIDAQAB
-----END PUBLIC KEY-----`,
"ATM8": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylXag4JmzoqaTK8eCcSj
DSOGRcrX8IK/fBawgEWKAgPy/yu+8FGXXK10XDeI1fmlAefDr7349Cn+v9/y+Mff
XIduKCqR5ZP9M1+fBk7k5l4x2SeC9NfIMG+c0yJ6m1kEmsSN04nlKk8foo54L7DY
+Kkjfh6EPxyzxsMDqqTrMifBThF2kqo5KUBDdBjIkOUH1dbLWGjEgUpKocCu2M41
U7jmjToatkA+d3V+PyQRF4/lJkTYiv6Jy1Zl1qpEkLvR0qKrzoHkOij7zBpQ/46B
2BW1pARjU7AIp3NtfS5THL59mpXxpuyj6y2h0wxNVRkPZpnVA0ZWHgz9J4TcIgAN
PwIDAQAB
-----END PUBLIC KEY-----`,
"ATM9": `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxa0XBIlBj9t5bYB81Cea
mlV3I3rTathgyUn2VL7/wng2vK5x7BB3a1wjXt5k/uwR/M5tfIDOSjug/SdDfTWk
ZRe82Ij/oYJOytcrFzEzouIZVA7t/uKdXzRwz7dZ6LPnNVkp8GiWUDCDpTNNmnvi
eZcjqofajDcc0EC720NT+NqmkAJd0qYMs+i4TA2om2C2Lxpkq+YdJp2pJOCCQquC
wmLXB8OxrddjX4QW5mHzigx4fanC/GJcXuRQPXqLruHZlWmUqU7Sl6yZEluItHbB
ri4BxD3Q7eXH0sM3rZGUCLr3lMPXjGsfpogZT4zLr075QIxtwe5OUpnslU61c34X
BwIDAQAB
-----END PUBLIC KEY-----`,
}
cert, err := x509.ParseCertificate(ekcert)
if err != nil {
return fmt.Errorf("Unable to parse EKCert: %s", err)
}
for vendor, certificate := range trustedCerts {
block, _ := pem.Decode([]byte(certificate))
testcert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return fmt.Errorf("Unable to parse %s: %s", vendor, err)
}
err = testcert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature)
if err == nil {
return nil
}
}
for vendor, key := range trustedKeys {
block, _ := pem.Decode([]byte(key))
pubkey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return fmt.Errorf("Unable to parse %s: %s", vendor, err)
}
hashdata := sha1.Sum(cert.RawTBSCertificate[:])
err = rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), crypto.SHA1, hashdata[:], cert.Signature)
if err == nil {
return nil
}
}
return fmt.Errorf("No matching certificate found")
}
// QuoteVerify verifies that a quote was genuinely provided by the TPM. It
// takes the quote data, quote validation blob, public half of the AIK,
// current PCR values and the nonce used in the original quote request. It
// then verifies that the validation block is a valid signature for the
// quote data, that the secrets are the same (in order to avoid replay
// attacks), and that the PCR values are the same. It returns an error if
// any stage of the validation fails.
func QuoteVerify(data []byte, validation []byte, aikpub []byte, pcrvalues [][]byte, secret []byte) error {
n := big.NewInt(0)
n.SetBytes(aikpub)
e := 65537
pKey := rsa.PublicKey{N: n, E: int(e)}
dataHash := sha1.Sum(data[:])
err := rsa.VerifyPKCS1v15(&pKey, crypto.SHA1, dataHash[:], validation)
if err != nil {
return err
}
pcrHash := data[8:28]
nonceHash := data[28:48]
secretHash := sha1.Sum(secret[:])
if bytes.Equal(secretHash[:], nonceHash) == false {
return fmt.Errorf("Secret doesn't match")
}
pcrComposite := []byte{0x00, 0x02, 0xff, 0xff, 0x00, 0x00, 0x01, 0x40}
for i := 0; i < 16; i++ {
pcrComposite = append(pcrComposite, pcrvalues[i]...)
}
pcrCompositeHash := sha1.Sum(pcrComposite[:])
if bytes.Equal(pcrCompositeHash[:], pcrHash) == false {
return fmt.Errorf("PCR values don't match")
}
return nil
}
// KeyVerify verifies that a key certification request was genuinely
// provided by the TPM. It takes the certification data, certification
// validation blob, the public half of the AIK, the public half of the key
// to be certified and the nonce used in the original quote request. It then
// verifies that the validation block is a valid signature for the
// certification data, that the certification data matches the certified key
// and that the secrets are the same (in order to avoid replay attacks). It
// returns an error if any stage of the validation fails.
func KeyVerify(data []byte, validation []byte, aikpub []byte, keypub []byte, secret []byte) error {
n := big.NewInt(0)
n.SetBytes(aikpub)
e := 65537
pKey := rsa.PublicKey{N: n, E: int(e)}
dataHash := sha1.Sum(data[:])
err := rsa.VerifyPKCS1v15(&pKey, crypto.SHA1, dataHash[:], validation)
if err != nil {
return err
}
keyHash := data[43:63]
nonceHash := data[63:83]
secretHash := sha1.Sum(secret[:])
if bytes.Equal(secretHash[:], nonceHash) == false {
return fmt.Errorf("Secret doesn't match")
}
certHash := sha1.Sum(keypub[:])
if bytes.Equal(certHash[:], keyHash) == false {
return fmt.Errorf("Key doesn't match")
}
return nil
}