mirror of
https://github.com/google/go-attestation.git
synced 2024-12-21 13:57:55 +00:00
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.
This commit is contained in:
parent
f3f08037f8
commit
7d7676beda
@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/certificate-transparency-go/x509"
|
||||
"github.com/google/go-tpm/tpm"
|
||||
"github.com/google/go-tpm/tpm2"
|
||||
)
|
||||
|
||||
@ -100,7 +101,6 @@ type aik interface {
|
||||
ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error)
|
||||
Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error)
|
||||
AttestationParameters() AttestationParameters
|
||||
Public() crypto.PublicKey
|
||||
}
|
||||
|
||||
// AIK represents a key which can be used for attestation.
|
||||
@ -138,11 +138,6 @@ func (k *AIK) AttestationParameters() AttestationParameters {
|
||||
return k.aik.AttestationParameters()
|
||||
}
|
||||
|
||||
// Public returns the public part of the AIK.
|
||||
func (k *AIK) Public() crypto.PublicKey {
|
||||
return k.aik.Public()
|
||||
}
|
||||
|
||||
// MintOptions encapsulates parameters for minting keys. This type is defined
|
||||
// now (despite being empty) for future interface compatibility.
|
||||
type MintOptions struct {
|
||||
@ -180,12 +175,16 @@ type PlatformEK struct {
|
||||
// AttestationParameters describes information about a key which is necessary
|
||||
// for verifying its properties remotely.
|
||||
type AttestationParameters struct {
|
||||
// Public represents the public key in a TPM-version specific encoding.
|
||||
// For TPM 2.0 devices, this is encoded as a TPMT_PUBLIC structure.
|
||||
// For TPM 1.2 devices, this is a TPM_PUBKEY structure, as defined in
|
||||
// Public represents the AIK's canonical encoding. This blob includes the
|
||||
// public key, as well as signing parameters such as the hash algorithm
|
||||
// used to generate quotes.
|
||||
//
|
||||
// Use ParseAIKPublic to access the key's data.
|
||||
Public []byte
|
||||
// For TPM 2.0 devices, Public is encoded as a TPMT_PUBLIC structure.
|
||||
// For TPM 1.2 devices, Public is a TPM_PUBKEY structure, as defined in
|
||||
// the TPM Part 2 Structures specification, available at
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/TPM-Main-Part-2-TPM-Structures_v1.2_rev116_01032011.pdf
|
||||
Public []byte
|
||||
|
||||
// UseTCSDActivationFormat is set when tcsd (trousers daemon) is operating
|
||||
// as an intermediary between this library and the TPM. A value of true
|
||||
@ -209,6 +208,52 @@ type AttestationParameters struct {
|
||||
CreateSignature []byte
|
||||
}
|
||||
|
||||
// AIKPublic holds structured information about an AIK's public key.
|
||||
type AIKPublic struct {
|
||||
// Public is the public part of the AIK. This can either be an *rsa.PublicKey or
|
||||
// and *ecdsa.PublicKey.
|
||||
Public crypto.PublicKey
|
||||
// Hash is the hashing algorithm the AIK will use when signing quotes.
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
||||
// ParseAIKPublic parses the Public blob from the AttestationParameters,
|
||||
// returning the public key and signing parameters for the key.
|
||||
func ParseAIKPublic(version TPMVersion, public []byte) (*AIKPublic, error) {
|
||||
switch version {
|
||||
case TPMVersion12:
|
||||
rsaPub, err := tpm.UnmarshalPubRSAPublicKey(public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing public key: %v", err)
|
||||
}
|
||||
return &AIKPublic{Public: rsaPub, Hash: crypto.SHA1}, nil
|
||||
case TPMVersion20:
|
||||
pub, err := tpm2.DecodePublic(public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing TPM public key structure: %v", err)
|
||||
}
|
||||
pubKey, err := pub.Key()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing public key: %v", err)
|
||||
}
|
||||
var h crypto.Hash
|
||||
switch pub.Type {
|
||||
case tpm2.AlgRSA:
|
||||
h, err = cryptoHash(pub.RSAParameters.Sign.Hash)
|
||||
case tpm2.AlgECC:
|
||||
h, err = cryptoHash(pub.ECCParameters.Sign.Hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported public key type 0x%x", pub.Type)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid public key hash: %v", err)
|
||||
}
|
||||
return &AIKPublic{Public: pubKey, Hash: h}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown tpm version 0x%x", version)
|
||||
}
|
||||
}
|
||||
|
||||
// HashAlg identifies a hashing Algorithm.
|
||||
type HashAlg uint8
|
||||
|
||||
|
@ -153,6 +153,21 @@ func TestSimTPM20ActivateCredential(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAIKPublic20(t *testing.T) {
|
||||
sim, tpm := setupSimulatedTPM(t)
|
||||
defer sim.Close()
|
||||
|
||||
aik, err := tpm.MintAIK(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("MintAIK() failed: %v", err)
|
||||
}
|
||||
defer aik.Close(tpm)
|
||||
params := aik.AttestationParameters()
|
||||
if _, err := ParseAIKPublic(TPMVersion20, params.Public); err != nil {
|
||||
t.Errorf("parsing AIK public blob: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimTPM20Quote(t *testing.T) {
|
||||
sim, tpm := setupSimulatedTPM(t)
|
||||
defer sim.Close()
|
||||
|
@ -27,7 +27,7 @@ var (
|
||||
tpm12config = &OpenConfig{TPMVersion12}
|
||||
)
|
||||
|
||||
func TestTPM12Info(t *testing.T) {
|
||||
func openTPM12(t *testing.T) *TPM {
|
||||
if !*testTPM12 {
|
||||
t.SkipNow()
|
||||
}
|
||||
@ -35,6 +35,11 @@ func TestTPM12Info(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open tpm 1.2: %v", err)
|
||||
}
|
||||
return tpm
|
||||
}
|
||||
|
||||
func TestTPM12Info(t *testing.T) {
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
Info, err := tpm.Info()
|
||||
@ -46,13 +51,7 @@ func TestTPM12Info(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTPM12PCRs(t *testing.T) {
|
||||
if !*testTPM12 {
|
||||
t.SkipNow()
|
||||
}
|
||||
tpm, err := OpenTPM(tpm12config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open tpm 1.2: %v", err)
|
||||
}
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
PCRs, _, err := tpm.PCRs()
|
||||
@ -75,13 +74,7 @@ func TestTPM12PCRs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTPM12EKs(t *testing.T) {
|
||||
if !*testTPM12 {
|
||||
t.SkipNow()
|
||||
}
|
||||
tpm, err := OpenTPM(tpm12config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open tpm 1.2: %v", err)
|
||||
}
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
EKs, err := tpm.EKs()
|
||||
@ -97,13 +90,7 @@ func TestTPM12EKs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMintAIK(t *testing.T) {
|
||||
if !*testTPM12 {
|
||||
t.SkipNow()
|
||||
}
|
||||
tpm, err := OpenTPM(tpm12config)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open tpm 1.2: %v", err)
|
||||
}
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
aik, err := tpm.MintAIK(nil)
|
||||
@ -115,18 +102,14 @@ func TestMintAIK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTPMQuote(t *testing.T) {
|
||||
if !*testTPM12 {
|
||||
t.SkipNow()
|
||||
}
|
||||
nonce := make([]byte, 20)
|
||||
rand.Read(nonce)
|
||||
|
||||
tpm, err := OpenTPM(tpm12config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open tpm 1.2: %v", err)
|
||||
}
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
nonce := make([]byte, 20)
|
||||
if _, err := rand.Read(nonce); err != nil {
|
||||
t.Fatalf("reading nonce: %v", err)
|
||||
}
|
||||
|
||||
aik, err := tpm.MintAIK(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("MintAIK failed: %v", err)
|
||||
@ -140,15 +123,23 @@ func TestTPMQuote(t *testing.T) {
|
||||
t.Logf("Quote{version: %v, quote: %x, signature: %x}\n", quote.Version, quote.Quote, quote.Signature)
|
||||
}
|
||||
|
||||
func TestTPMActivateCredential(t *testing.T) {
|
||||
if !*testTPM12 {
|
||||
t.SkipNow()
|
||||
}
|
||||
func TestParseAIKPublic12(t *testing.T) {
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
tpm, err := OpenTPM(tpm12config)
|
||||
aik, err := tpm.MintAIK(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open tpm 1.2: %v", err)
|
||||
t.Fatalf("MintAIK() failed: %v", err)
|
||||
}
|
||||
defer aik.Close(tpm)
|
||||
params := aik.AttestationParameters()
|
||||
if _, err := ParseAIKPublic(TPMVersion12, params.Public); err != nil {
|
||||
t.Errorf("parsing AIK public blob: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTPMActivateCredential(t *testing.T) {
|
||||
tpm := openTPM12(t)
|
||||
defer tpm.Close()
|
||||
|
||||
aik, err := tpm.MintAIK(nil)
|
||||
|
@ -17,10 +17,8 @@
|
||||
package attest
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-tpm/tpm"
|
||||
"github.com/google/go-tpm/tpm2"
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
"github.com/google/go-tspi/attestation"
|
||||
@ -30,20 +28,13 @@ import (
|
||||
type key12 struct {
|
||||
blob []byte
|
||||
public []byte
|
||||
|
||||
publicKey crypto.PublicKey
|
||||
}
|
||||
|
||||
func newKey12(blob, public []byte) (aik, error) {
|
||||
rsaPub, err := tpm.UnmarshalPubRSAPublicKey(public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing public key: %v", err)
|
||||
}
|
||||
func newKey12(blob, public []byte) aik {
|
||||
return &key12{
|
||||
blob: blob,
|
||||
public: public,
|
||||
publicKey: rsaPub,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal represents the key in a persistent format which may be
|
||||
@ -86,10 +77,6 @@ func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *key12) Public() crypto.PublicKey {
|
||||
return k.publicKey
|
||||
}
|
||||
|
||||
// AttestationParameters returns information about the AIK.
|
||||
func (k *key12) AttestationParameters() AttestationParameters {
|
||||
return AttestationParameters{
|
||||
@ -107,19 +94,9 @@ type key20 struct {
|
||||
createData []byte
|
||||
createAttestation []byte
|
||||
createSignature []byte
|
||||
|
||||
publicKey crypto.PublicKey
|
||||
}
|
||||
|
||||
func newKey20(hnd tpmutil.Handle, blob, public, createData, createAttestation, createSig []byte) (aik, error) {
|
||||
pub, err := tpm2.DecodePublic(public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing TPM public key structure: %v", err)
|
||||
}
|
||||
pubKey, err := pub.Key()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing public key: %v", err)
|
||||
}
|
||||
func newKey20(hnd tpmutil.Handle, blob, public, createData, createAttestation, createSig []byte) aik {
|
||||
return &key20{
|
||||
hnd: hnd,
|
||||
blob: blob,
|
||||
@ -127,8 +104,7 @@ func newKey20(hnd tpmutil.Handle, blob, public, createData, createAttestation, c
|
||||
createData: createData,
|
||||
createAttestation: createAttestation,
|
||||
createSignature: createSig,
|
||||
publicKey: pubKey,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal represents the key in a persistent format which may be
|
||||
@ -197,7 +173,3 @@ func (k *key20) AttestationParameters() AttestationParameters {
|
||||
CreateSignature: k.createSignature,
|
||||
}
|
||||
}
|
||||
|
||||
func (k *key20) Public() crypto.PublicKey {
|
||||
return k.publicKey
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package attest
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"fmt"
|
||||
|
||||
tpm1 "github.com/google/go-tpm/tpm"
|
||||
@ -29,25 +28,14 @@ type key12 struct {
|
||||
hnd uintptr
|
||||
pcpKeyName string
|
||||
public []byte
|
||||
|
||||
publicKey crypto.PublicKey
|
||||
}
|
||||
|
||||
func newKey12(hnd uintptr, pcpKeyName string, public []byte) (aik, error) {
|
||||
rsaPub, err := tpm1.UnmarshalPubRSAPublicKey(public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing public key: %v", err)
|
||||
}
|
||||
func newKey12(hnd uintptr, pcpKeyName string, public []byte) aik {
|
||||
return &key12{
|
||||
hnd: hnd,
|
||||
pcpKeyName: pcpKeyName,
|
||||
public: public,
|
||||
publicKey: rsaPub,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *key12) Public() crypto.PublicKey {
|
||||
return k.publicKey
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal represents the key in a persistent format which may be
|
||||
@ -127,19 +115,9 @@ type key20 struct {
|
||||
createData []byte
|
||||
createAttestation []byte
|
||||
createSignature []byte
|
||||
|
||||
publicKey crypto.PublicKey
|
||||
}
|
||||
|
||||
func newKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest, createSig []byte) (aik, error) {
|
||||
pub, err := tpm2.DecodePublic(public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing TPM public key structure: %v", err)
|
||||
}
|
||||
pubKey, err := pub.Key()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing public key: %v", err)
|
||||
}
|
||||
func newKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest, createSig []byte) aik {
|
||||
return &key20{
|
||||
hnd: hnd,
|
||||
pcpKeyName: pcpKeyName,
|
||||
@ -147,12 +125,7 @@ func newKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest,
|
||||
createData: createData,
|
||||
createAttestation: createAttest,
|
||||
createSignature: createSig,
|
||||
publicKey: pubKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *key20) Public() crypto.PublicKey {
|
||||
return k.publicKey
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal represents the key in a persistent format which may be
|
||||
|
@ -274,11 +274,7 @@ func (t *TPM) MintAIK(opts *MintOptions) (*AIK, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateAIK failed: %v", err)
|
||||
}
|
||||
aik, err := newKey12(blob, pub)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("")
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey12(blob, pub)}, nil
|
||||
case TPMVersion20:
|
||||
// TODO(jsonp): Abstract choice of hierarchy & parent.
|
||||
srk, _, err := t.getPrimaryKeyHandle(commonSrkEquivalentHandle)
|
||||
@ -311,12 +307,7 @@ func (t *TPM) MintAIK(opts *MintOptions) (*AIK, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to pack TPMT_SIGNATURE: %v", err)
|
||||
}
|
||||
|
||||
aik, err := newKey20(keyHandle, blob, pub, creationData, attestation, signature)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking public key: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey20(keyHandle, blob, pub, creationData, attestation, signature)}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported TPM version: %x", t.version)
|
||||
}
|
||||
@ -333,11 +324,7 @@ func (t *TPM) loadAIK(opaqueBlob []byte) (*AIK, error) {
|
||||
|
||||
switch sKey.TPMVersion {
|
||||
case TPMVersion12:
|
||||
aik, err := newKey12(sKey.Blob, sKey.Public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking aik: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey12(sKey.Blob, sKey.Public)}, nil
|
||||
case TPMVersion20:
|
||||
srk, _, err := t.getPrimaryKeyHandle(commonSrkEquivalentHandle)
|
||||
if err != nil {
|
||||
@ -347,12 +334,7 @@ func (t *TPM) loadAIK(opaqueBlob []byte) (*AIK, error) {
|
||||
if hnd, _, err = tpm2.Load(t.rwc, srk, "", sKey.Public, sKey.Blob); err != nil {
|
||||
return nil, fmt.Errorf("Load() failed: %v", err)
|
||||
}
|
||||
|
||||
aik, err := newKey20(hnd, sKey.Blob, sKey.Public, sKey.CreateData, sKey.CreateAttestation, sKey.CreateSignature)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking aik: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey20(hnd, sKey.Blob, sKey.Public, sKey.CreateData, sKey.CreateAttestation, sKey.CreateSignature)}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot load AIK with TPM version: %v", sKey.TPMVersion)
|
||||
}
|
||||
|
@ -311,17 +311,9 @@ func (t *TPM) MintAIK(opts *MintOptions) (*AIK, error) {
|
||||
|
||||
switch t.version {
|
||||
case TPMVersion12:
|
||||
aik, err := newKey12(kh, name, props.RawPublic)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking aik: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey12(kh, name, props.RawPublic)}, nil
|
||||
case TPMVersion20:
|
||||
aik, err := newKey20(kh, name, props.RawPublic, props.RawCreationData, props.RawAttest, props.RawSignature)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking aik: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey20(kh, name, props.RawPublic, props.RawCreationData, props.RawAttest, props.RawSignature)}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot handle TPM version: %v", t.version)
|
||||
}
|
||||
@ -343,17 +335,9 @@ func (t *TPM) loadAIK(opaqueBlob []byte) (*AIK, error) {
|
||||
|
||||
switch t.version {
|
||||
case TPMVersion12:
|
||||
aik, err := newKey12(hnd, sKey.Name, sKey.Public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking aik: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey12(hnd, sKey.Name, sKey.Public)}, nil
|
||||
case TPMVersion20:
|
||||
aik, err := newKey20(hnd, sKey.Name, sKey.Public, sKey.CreateData, sKey.CreateAttestation, sKey.CreateSignature)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unpacking aik: %v", err)
|
||||
}
|
||||
return &AIK{aik: aik}, nil
|
||||
return &AIK{aik: newKey20(hnd, sKey.Name, sKey.Public, sKey.CreateData, sKey.CreateAttestation, sKey.CreateSignature)}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot handle TPM version: %v", t.version)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user