go-attestation/attest/key_windows.go
Eric Chiang 7d7676beda attest: move public key parsing server side
Event log parsing requires knowning both the public key and signing
parameters. Symmantically, this information should be from an attested
public key blob, not additional data passed by the client.

Introduce a new method for parsing an AIK's public key blob, returning
a new AIKPublic struct.
2019-08-06 11:09:20 -07:00

187 lines
5.3 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"
"github.com/google/go-tpm/tpm2"
)
// 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,
}
}
// Marshal represents the key in a persistent format which may be
// loaded at a later time using tpm.LoadKey().
func (k *key12) Marshal() ([]byte, error) {
out := serializedKey{
Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion12,
Name: k.pcpKeyName,
Public: k.public,
}
return out.Serialize()
}
// ActivateCredential decrypts the specified credential using key.
// This operation is synonymous with TPM_ActivateIdentity for TPM1.2.
func (k *key12) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) {
secretKey, err := tpm.pcp.ActivateCredential(k.hnd, in.Credential)
if err != nil {
return nil, err
}
return decryptCredential(secretKey, in.Secret)
}
// Quote returns a quote over the platform state, signed by the key.
func (k *key12) Quote(t *TPM, 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)
}
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{
Quote: quote,
Signature: sig,
}, nil
}
// Close frees any resources associated with the key.
func (k *key12) Close(tpm *TPM) error {
return closeNCryptObject(k.hnd)
}
// AttestationParameters returns information about the AIK.
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,
}
}
// Marshal represents the key in a persistent format which may be
// loaded at a later time using tpm.LoadKey().
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()
}
// ActivateCredential decrypts the specified credential using the key.
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key20) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) {
return tpm.pcp.ActivateCredential(k.hnd, append(in.Credential, in.Secret...))
}
// Quote returns a quote over the platform state, signed by the key.
func (k *key20) Quote(t *TPM, 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, tpm2.Algorithm(alg), nonce)
}
// Close frees any resources associated with the key.
func (k *key20) Close(tpm *TPM) error {
return closeNCryptObject(k.hnd)
}
// Delete permenantly removes the key from the system. This method
// invalidates Key and any further method invocations are invalid.
func (k *key20) Delete(tpm *TPM) error {
return tpm.pcp.DeleteKey(k.hnd)
}
// AttestationParameters returns information about the AIK.
func (k *key20) AttestationParameters() AttestationParameters {
return AttestationParameters{
Public: k.public,
CreateData: k.createData,
CreateAttestation: k.createAttestation,
CreateSignature: k.createSignature,
}
}