From 0f31ae47d76b9c8258e493cfd85ab58f3d925309 Mon Sep 17 00:00:00 2001 From: Tom Roeder Date: Fri, 26 Apr 2019 17:14:19 -0700 Subject: [PATCH] Add a tpm-startup example. This is used in setting up a software TPM emulator for testing. It sends the startup command, which is normally not needed for user-level libraries. --- examples/tpm-startup/startup.go | 41 +++++++++++++++++++++++++++++++++ tpm/constants.go | 11 +++++++++ tpm/tpm.go | 6 +++++ tpm/tpm_test.go | 13 +++++++++++ 4 files changed, 71 insertions(+) create mode 100644 examples/tpm-startup/startup.go diff --git a/examples/tpm-startup/startup.go b/examples/tpm-startup/startup.go new file mode 100644 index 00000000..ada470de --- /dev/null +++ b/examples/tpm-startup/startup.go @@ -0,0 +1,41 @@ +// Copyright (c) 2019, Google LLC. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/google/go-tpm/tpm" +) + +func main() { + var tpmname = flag.String("tpm", "/dev/tpm0", "The path to the TPM device to use") + flag.Parse() + + rwc, err := tpm.OpenTPM(*tpmname) + if err != nil { + fmt.Fprintf(os.Stderr, "Couldn't open the TPM file %s: %s\n", *tpmname, err) + return + } + + if err := tpm.Startup(rwc, tpm.StartupClear); err != nil { + fmt.Fprintf(os.Stderr, "Couldn't start up the TPM: %s\n", err) + return + } + + return +} diff --git a/tpm/constants.go b/tpm/constants.go index 3b5b4f5f..fad3b7eb 100644 --- a/tpm/constants.go +++ b/tpm/constants.go @@ -50,6 +50,7 @@ const ( ordMakeIdentity uint32 = 0x00000079 ordActivateIdentity uint32 = 0x0000007A ordReadPubEK uint32 = 0x0000007C + ordStartup uint32 = 0x00000099 ordOwnerReadInternalPub uint32 = 0x00000081 ordFlushSpecific uint32 = 0x000000BA ordPcrReset uint32 = 0x000000C8 @@ -162,6 +163,16 @@ const ( authPrivUseOnly byte = 0x03 ) +type StartupMode uint16 + +// The startup modes for the Startup command. +const ( + _ StartupMode = iota + StartupClear + StartupWithState + StartupDeactivated +) + // fixedQuote is the fixed constant string used in quoteInfo. var fixedQuote = [4]byte{byte('Q'), byte('U'), byte('O'), byte('T')} diff --git a/tpm/tpm.go b/tpm/tpm.go index 2ab9dc5d..26591307 100644 --- a/tpm/tpm.go +++ b/tpm/tpm.go @@ -1254,6 +1254,12 @@ func ForceClear(rw io.ReadWriter) error { in := []interface{}{} out := []interface{}{} _, err := submitTPMRequest(rw, tagRQUCommand, ordForceClear, in, out) + return err +} +// Startup starts a TPM. This is not necessary for hardware TPMs, but it is +// sometimes needed for software emulators. +func Startup(rw io.ReadWriter, mode StartupMode) error { + _, err := submitTPMRequest(rw, tagRQUCommand, ordStartup, []interface{}{mode}, nil) return err } diff --git a/tpm/tpm_test.go b/tpm/tpm_test.go index fdfb18e9..9b7ca21d 100644 --- a/tpm/tpm_test.go +++ b/tpm/tpm_test.go @@ -554,3 +554,16 @@ func TestForceClear(t *testing.T) { t.Fatal("Couldn't clear the TPM without owner auth in physical presence mode:", err) } } + +func TestStartup(t *testing.T) { + // This only works if startup has not yet been performed. On TPM 1.2 + // hardware, this happens at a lower level in the stack. However, this + // can be tested against emulators. + t.Skip() + rwc := openTPMOrSkip(t) + defer rwc.Close() + + if err := Startup(rwc, StartupClear); err != nil { + t.Fatal("Couldn't start the TPM") + } +}