go-attestation/attest/attest.go

200 lines
5.0 KiB
Go

// Copyright 2019 Google 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 attest abstracts TPM attestation operations.
package attest
import (
"crypto"
"errors"
"github.com/google/certificate-transparency-go/x509"
)
// TPMVersion is used to configure a preference in
// which TPM to use, if multiple are available.
type TPMVersion uint8
// TPM versions
const (
TPMVersionAgnostic TPMVersion = iota
TPMVersion12
TPMVersion20
)
// TPMInterface indicates how the client communicates
// with the TPM.
type TPMInterface uint8
// TPM interfaces
const (
TPMInterfaceDirect TPMInterface = iota
TPMInterfaceKernelManaged
TPMInterfaceDaemonManaged
)
// OpenConfig encapsulates settings passed to OpenTPM().
type OpenConfig struct {
// TPMVersion indicates which TPM version the library should
// attempt to use. If the specified version is not available,
// ErrTPMNotAvailable is returned. Defaults to TPMVersionAgnostic.
TPMVersion TPMVersion
}
// KeyEncoding indicates how an exported TPM key is represented.
type KeyEncoding uint8
// Key encodings
const (
KeyEncodingInvalid KeyEncoding = iota
// Managed by the OS but loadable by name.
KeyEncodingOSManaged
// Key fully represented but in encrypted form.
KeyEncodingEncrypted
// Parameters stored, but key must be regenerated before use.
KeyEncodingParameterized
)
// KeyPurpose indicates the intended use of the key. It is implied that
// the key was created with usage restrictions to constrain its use
// to the given purpose.
type KeyPurpose uint8
// Key purposes.
const (
AttestationKey KeyPurpose = iota
StorageKey
)
// MintOptions encapsulates parameters for minting keys. This type is defined
// now (despite being empty) for future interface compatibility.
type MintOptions struct {
}
// EncryptedCredential represents encrypted parameters which must be activated
// against a key.
type EncryptedCredential struct {
Credential []byte
Secret []byte
}
// Quote encapsulates the results of a Quote operation against the TPM,
// using an attestation key.
type Quote struct {
Version TPMVersion
Quote []byte
Signature []byte
}
// PCR encapsulates the value of a PCR at a point in time.
type PCR struct {
Index int
Digest []byte
DigestAlg crypto.Hash
}
// PlatformEK represents a burned-in Endorsement Key, and its
// corrresponding EKCert (where present).
type PlatformEK struct {
Cert *x509.Certificate
Public crypto.PublicKey
}
var (
defaultOpenConfig = &OpenConfig{}
// ErrTPMNotAvailable is returned in response to OpenTPM() when
// either no TPM is available, or a TPM of the requested version
// is not available (if TPMVersion was set in the provided config).
ErrTPMNotAvailable = errors.New("TPM device not available")
// ErrTPM12NotImplemented is returned in response to methods which
// need to interact with the TPM1.2 device in ways that have not
// yet been implemented.
ErrTPM12NotImplemented = errors.New("TPM 1.2 support not yet implemented")
)
// TPMInfo contains information about the version & interface
// of an open TPM.
type TPMInfo struct {
Version TPMVersion
Interface TPMInterface
VendorInfo string
Manufacturer TCGVendorID
}
// probedTPM identifies a TPM device on the system, which
// is a candidate for being used.
type probedTPM struct {
Version TPMVersion
Path string
}
// MatchesConfig returns true if the TPM satisfies the constraints
// specified by the given config.
func (t *probedTPM) MatchesConfig(config OpenConfig) bool {
return config.TPMVersion == TPMVersionAgnostic || t.Version == config.TPMVersion
}
// OpenTPM initializes access to the TPM based on the
// config provided.
func OpenTPM(config *OpenConfig) (*TPM, error) {
if config == nil {
config = defaultOpenConfig
}
candidateTPMs, err := probeSystemTPMs()
if err != nil {
return nil, err
}
for _, tpm := range candidateTPMs {
if tpm.MatchesConfig(*config) {
return openTPM(tpm)
}
}
return nil, ErrTPMNotAvailable
}
// AvailableTPMs returns information about available TPMs matching
// the given config, without opening the devices.
func AvailableTPMs(config *OpenConfig) ([]TPMInfo, error) {
if config == nil {
config = defaultOpenConfig
}
candidateTPMs, err := probeSystemTPMs()
if err != nil {
return nil, err
}
var out []TPMInfo
for _, tpm := range candidateTPMs {
if tpm.MatchesConfig(*config) {
t, err := openTPM(tpm)
if err != nil {
return nil, err
}
defer t.Close()
i, err := t.Info()
if err != nil {
return nil, err
}
out = append(out, *i)
}
}
return out, nil
}