mirror of
https://github.com/google/go-attestation.git
synced 2025-02-21 09:11:46 +00:00
Merge pull request #62 from ericchiang/aik_pub
attest: move public key parsing server side
This commit is contained in:
commit
3a523cf51f
@ -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"
|
||||
)
|
||||
|
||||
@ -89,7 +90,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.
|
||||
@ -129,11 +129,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 {
|
||||
@ -171,12 +166,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
|
||||
@ -200,6 +199,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
|
||||
blob: blob,
|
||||
public: public,
|
||||
}
|
||||
}
|
||||
|
||||
// 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…
x
Reference in New Issue
Block a user