go-attestation/attest/key_windows.go
Eric Chiang 39d2f6efff attest: don't define exported API in files with build tags
It's best practice to define as much code, especially exported API, in
files that can build on any platform. With as little code as possible in
OS specific files.

Ensure files with build tags don't contain any exported APIs. This helps
us not accidentally define API that only works on one platform, or have
incompatible method defintions between OSes.

TODO: follow up with an "unsupported" implementation so this builds on
Mac or without CGO (e.g. for servers)?
2019-09-19 13:50:38 -07:00

171 lines
4.4 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.
// +build windows
package attest
import (
"fmt"
tpm1 "github.com/google/go-tpm/tpm"
)
// key12 represents a Windows-managed key on a TPM1.2 TPM.
type key12 struct {
hnd uintptr
pcpKeyName string
public []byte
}
func newKey12(hnd uintptr, pcpKeyName string, public []byte) aik {
return &key12{
hnd: hnd,
pcpKeyName: pcpKeyName,
public: public,
}
}
func (k *key12) marshal() ([]byte, error) {
out := serializedKey{
Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion12,
Name: k.pcpKeyName,
Public: k.public,
}
return out.Serialize()
}
func (k *key12) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error) {
secretKey, err := tpm.pcp.ActivateCredential(k.hnd, in.Credential)
if err != nil {
return nil, err
}
return decryptCredential(secretKey, in.Secret)
}
func (k *key12) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
if alg != HashSHA1 {
return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not HashAlg(%v)", alg)
}
tpmKeyHnd, err := t.pcp.TPMKeyHandle(k.hnd)
if err != nil {
return nil, fmt.Errorf("TPMKeyHandle() failed: %v", err)
}
tpm, err := t.pcp.TPMCommandInterface()
if err != nil {
return nil, fmt.Errorf("TPMCommandInterface() failed: %v", err)
}
selectedPCRs := make([]int, 24)
for pcr, _ := range selectedPCRs {
selectedPCRs[pcr] = pcr
}
sig, pcrc, err := tpm1.Quote(tpm, tpmKeyHnd, nonce, selectedPCRs[:], wellKnownAuth[:])
if err != nil {
return nil, fmt.Errorf("Quote() failed: %v", err)
}
// Construct and return TPM_QUOTE_INFO
// Returning TPM_QUOTE_INFO allows us to verify the Quote at a higher resolution
// and matches what go-tspi returns.
quote, err := tpm1.NewQuoteInfo(nonce, selectedPCRs[:], pcrc)
if err != nil {
return nil, fmt.Errorf("failed to construct Quote Info: %v", err)
}
return &Quote{
Version: TPMVersion12,
Quote: quote,
Signature: sig,
}, nil
}
func (k *key12) close(tpm *platformTPM) error {
return closeNCryptObject(k.hnd)
}
func (k *key12) attestationParameters() AttestationParameters {
return AttestationParameters{
Public: k.public,
}
}
// key20 represents a key bound to a TPM 2.0.
type key20 struct {
hnd uintptr
pcpKeyName string
public []byte
createData []byte
createAttestation []byte
createSignature []byte
}
func newKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest, createSig []byte) aik {
return &key20{
hnd: hnd,
pcpKeyName: pcpKeyName,
public: public,
createData: createData,
createAttestation: createAttest,
createSignature: createSig,
}
}
func (k *key20) marshal() ([]byte, error) {
out := serializedKey{
Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion20,
Name: k.pcpKeyName,
Public: k.public,
CreateData: k.createData,
CreateAttestation: k.createAttestation,
CreateSignature: k.createSignature,
}
return out.Serialize()
}
func (k *key20) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error) {
return tpm.pcp.ActivateCredential(k.hnd, append(in.Credential, in.Secret...))
}
func (k *key20) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
tpmKeyHnd, err := t.pcp.TPMKeyHandle(k.hnd)
if err != nil {
return nil, fmt.Errorf("TPMKeyHandle() failed: %v", err)
}
tpm, err := t.pcp.TPMCommandInterface()
if err != nil {
return nil, fmt.Errorf("TPMCommandInterface() failed: %v", err)
}
return quote20(tpm, tpmKeyHnd, alg.goTPMAlg(), nonce)
}
func (k *key20) close(tpm *platformTPM) error {
return closeNCryptObject(k.hnd)
}
func (k *key20) attestationParameters() AttestationParameters {
return AttestationParameters{
Public: k.public,
CreateData: k.createData,
CreateAttestation: k.createAttestation,
CreateSignature: k.createSignature,
}
}