mirror of
https://github.com/google/go-attestation.git
synced 2024-12-19 21:17:58 +00:00
attest: Create keys under non-default SRKs (#342)
This commit is contained in:
parent
310e2caafe
commit
046550658b
@ -72,6 +72,10 @@ type KeyConfig struct {
|
||||
// Size is used to specify the bit size of the key or elliptic curve. For
|
||||
// example, '256' is used to specify curve P-256.
|
||||
Size int
|
||||
// Parent describes the Storage Root Key that will be used as a parent.
|
||||
// If nil, the default SRK (i.e. RSA with handle 0x81000001) is assumed.
|
||||
// Supported only by TPM 2.0 on Linux.
|
||||
Parent *ParentKeyConfig
|
||||
}
|
||||
|
||||
// defaultConfig is used when no other configuration is specified.
|
||||
|
@ -99,6 +99,18 @@ const (
|
||||
keyEncodingParameterized
|
||||
)
|
||||
|
||||
// ParentKeyConfig describes the Storage Root Key that is used
|
||||
// as a parent for new keys.
|
||||
type ParentKeyConfig struct {
|
||||
Algorithm Algorithm
|
||||
Handle tpmutil.Handle
|
||||
}
|
||||
|
||||
var defaultParentConfig = ParentKeyConfig{
|
||||
Algorithm: RSA,
|
||||
Handle: 0x81000001,
|
||||
}
|
||||
|
||||
type ak interface {
|
||||
close(tpmBase) error
|
||||
marshal() ([]byte, error)
|
||||
@ -176,9 +188,12 @@ func (k *AK) Certify(tpm *TPM, handle interface{}) (*CertificationParameters, er
|
||||
return k.ak.certify(tpm.tpm, handle)
|
||||
}
|
||||
|
||||
// AKConfig encapsulates parameters for minting keys. This type is defined
|
||||
// now (despite being empty) for future interface compatibility.
|
||||
// AKConfig encapsulates parameters for minting keys.
|
||||
type AKConfig struct {
|
||||
// Parent describes the Storage Root Key that will be used as a parent.
|
||||
// If nil, the default SRK (i.e. RSA with handle 0x81000001) is assumed.
|
||||
// Supported only by TPM 2.0 on Linux.
|
||||
Parent *ParentKeyConfig
|
||||
}
|
||||
|
||||
// EncryptedCredential represents encrypted parameters which must be activated
|
||||
|
@ -260,23 +260,35 @@ func TestSimTPM20PCRs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSimTPM20PersistenceSRK(t *testing.T) {
|
||||
testPersistenceSRK(t, defaultParentConfig)
|
||||
}
|
||||
|
||||
func TestSimTPM20PersistenceECCSRK(t *testing.T) {
|
||||
parentConfig := ParentKeyConfig{
|
||||
Algorithm: ECDSA,
|
||||
Handle: 0x81000002,
|
||||
}
|
||||
testPersistenceSRK(t, parentConfig)
|
||||
}
|
||||
|
||||
func testPersistenceSRK(t *testing.T, parentConfig ParentKeyConfig) {
|
||||
sim, tpm := setupSimulatedTPM(t)
|
||||
defer sim.Close()
|
||||
|
||||
srkHnd, _, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(commonSrkEquivalentHandle)
|
||||
srkHnd, _, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(parentConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("getStorageRootKeyHandle() failed: %v", err)
|
||||
}
|
||||
if srkHnd != commonSrkEquivalentHandle {
|
||||
t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, commonSrkEquivalentHandle)
|
||||
if srkHnd != parentConfig.Handle {
|
||||
t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, parentConfig.Handle)
|
||||
}
|
||||
|
||||
srkHnd, p, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(commonSrkEquivalentHandle)
|
||||
srkHnd, p, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(parentConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("second getStorageRootKeyHandle() failed: %v", err)
|
||||
}
|
||||
if srkHnd != commonSrkEquivalentHandle {
|
||||
t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, commonSrkEquivalentHandle)
|
||||
if srkHnd != parentConfig.Handle {
|
||||
t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, parentConfig.Handle)
|
||||
}
|
||||
if p {
|
||||
t.Fatalf("generated a new key the second time; that shouldn't happen")
|
||||
|
@ -43,7 +43,6 @@ const (
|
||||
nvramECCEkNonceIndex = 0x1c0000b
|
||||
|
||||
// Defined in "Registry of reserved TPM 2.0 handles and localities", and checked on a glinux machine.
|
||||
commonSrkEquivalentHandle = 0x81000001
|
||||
commonRSAEkEquivalentHandle = 0x81010001
|
||||
commonECCEkEquivalentHandle = 0x81010002
|
||||
)
|
||||
@ -61,7 +60,7 @@ var (
|
||||
KeyBits: 2048,
|
||||
},
|
||||
}
|
||||
defaultSRKTemplate = tpm2.Public{
|
||||
defaultRSASRKTemplate = tpm2.Public{
|
||||
Type: tpm2.AlgRSA,
|
||||
NameAlg: tpm2.AlgSHA256,
|
||||
Attributes: tpm2.FlagStorageDefault | tpm2.FlagNoDA,
|
||||
@ -75,6 +74,23 @@ var (
|
||||
KeyBits: 2048,
|
||||
},
|
||||
}
|
||||
defaultECCSRKTemplate = tpm2.Public{
|
||||
Type: tpm2.AlgECC,
|
||||
NameAlg: tpm2.AlgSHA256,
|
||||
Attributes: tpm2.FlagStorageDefault | tpm2.FlagNoDA,
|
||||
ECCParameters: &tpm2.ECCParams{
|
||||
Symmetric: &tpm2.SymScheme{
|
||||
Alg: tpm2.AlgAES,
|
||||
KeyBits: 128,
|
||||
Mode: tpm2.AlgCFB,
|
||||
},
|
||||
CurveID: tpm2.CurveNISTP256,
|
||||
Point: tpm2.ECPoint{
|
||||
XRaw: make([]byte, 32),
|
||||
YRaw: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
}
|
||||
// Default RSA and ECC EK templates defined in:
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
|
||||
defaultRSAEKTemplate = tpm2.Public{
|
||||
@ -327,8 +343,10 @@ type tpmBase interface {
|
||||
info() (*TPMInfo, error)
|
||||
|
||||
loadAK(opaqueBlob []byte) (*AK, error)
|
||||
loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error)
|
||||
newAK(opts *AKConfig) (*AK, error)
|
||||
loadKey(opaqueBlob []byte) (*Key, error)
|
||||
loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error)
|
||||
newKey(ak *AK, opts *KeyConfig) (*Key, error)
|
||||
pcrs(alg HashAlg) ([]PCR, error)
|
||||
measurementLog() ([]byte, error)
|
||||
@ -370,6 +388,12 @@ func (t *TPM) LoadAK(opaqueBlob []byte) (*AK, error) {
|
||||
return t.tpm.loadAK(opaqueBlob)
|
||||
}
|
||||
|
||||
// LoadAKWithParent loads a previously-created ak into the TPM
|
||||
// under the given parent for use.
|
||||
func (t *TPM) LoadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) {
|
||||
return t.tpm.loadAKWithParent(opaqueBlob, parent)
|
||||
}
|
||||
|
||||
// MeasurementLog returns the present value of the System Measurement Log.
|
||||
//
|
||||
// This is a low-level API. Consumers seeking to attest the state of the
|
||||
|
@ -116,6 +116,10 @@ func (t *trousersTPM) loadKey(opaqueBlob []byte) (*Key, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (t *trousersTPM) loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (t *trousersTPM) newAK(opts *AKConfig) (*AK, error) {
|
||||
pub, blob, err := attestation.CreateAIK(t.ctx)
|
||||
if err != nil {
|
||||
@ -136,6 +140,10 @@ func (t *trousersTPM) loadAK(opaqueBlob []byte) (*AK, error) {
|
||||
return &AK{ak: newTrousersKey12(sKey.Blob, sKey.Public)}, nil
|
||||
}
|
||||
|
||||
func (t *trousersTPM) loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
// allPCRs12 returns a map of all the PCR values on the TPM
|
||||
func allPCRs12(ctx *tspi.Context) (map[uint32][]byte, error) {
|
||||
tpm := ctx.GetTPM()
|
||||
|
@ -337,6 +337,10 @@ func (t *windowsTPM) loadAK(opaqueBlob []byte) (*AK, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *windowsTPM) loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (t *windowsTPM) newKey(*AK, *KeyConfig) (*Key, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
@ -345,6 +349,10 @@ func (t *windowsTPM) loadKey(opaqueBlob []byte) (*Key, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (t *windowsTPM) loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func allPCRs12(tpm io.ReadWriter) (map[uint32][]byte, error) {
|
||||
numPCRs := 24
|
||||
out := map[uint32][]byte{}
|
||||
|
@ -148,26 +148,36 @@ func (t *wrappedTPM20) getEndorsementKeyHandle(ek *EK) (tpmutil.Handle, bool, er
|
||||
}
|
||||
|
||||
// Return value: handle, whether we generated a new one, error
|
||||
func (t *wrappedTPM20) getStorageRootKeyHandle(pHnd tpmutil.Handle) (tpmutil.Handle, bool, error) {
|
||||
_, _, _, err := tpm2.ReadPublic(t.rwc, pHnd)
|
||||
func (t *wrappedTPM20) getStorageRootKeyHandle(parent ParentKeyConfig) (tpmutil.Handle, bool, error) {
|
||||
srkHandle := parent.Handle
|
||||
_, _, _, err := tpm2.ReadPublic(t.rwc, srkHandle)
|
||||
if err == nil {
|
||||
// Found the persistent handle, assume it's the key we want.
|
||||
return pHnd, false, nil
|
||||
return srkHandle, false, nil
|
||||
}
|
||||
rerr := err // Preserve this failure for later logging, if needed
|
||||
|
||||
keyHnd, _, err := tpm2.CreatePrimary(t.rwc, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", defaultSRKTemplate)
|
||||
var srkTemplate tpm2.Public
|
||||
switch parent.Algorithm {
|
||||
case RSA:
|
||||
srkTemplate = defaultRSASRKTemplate
|
||||
case ECDSA:
|
||||
srkTemplate = defaultECCSRKTemplate
|
||||
default:
|
||||
return 0, false, fmt.Errorf("unsupported SRK algorithm: %v", parent.Algorithm)
|
||||
}
|
||||
keyHnd, _, err := tpm2.CreatePrimary(t.rwc, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", srkTemplate)
|
||||
if err != nil {
|
||||
return 0, false, fmt.Errorf("ReadPublic failed (%v), and then CreatePrimary failed: %v", rerr, err)
|
||||
}
|
||||
defer tpm2.FlushContext(t.rwc, keyHnd)
|
||||
|
||||
err = tpm2.EvictControl(t.rwc, "", tpm2.HandleOwner, keyHnd, pHnd)
|
||||
err = tpm2.EvictControl(t.rwc, "", tpm2.HandleOwner, keyHnd, srkHandle)
|
||||
if err != nil {
|
||||
return 0, false, fmt.Errorf("EvictControl failed: %v", err)
|
||||
}
|
||||
|
||||
return pHnd, true, nil
|
||||
return srkHandle, true, nil
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) ekCertificates() ([]EK, error) {
|
||||
@ -214,8 +224,13 @@ func (t *wrappedTPM20) eks() ([]EK, error) {
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) newAK(opts *AKConfig) (*AK, error) {
|
||||
// TODO(jsonp): Abstract choice of hierarchy & parent.
|
||||
srk, _, err := t.getStorageRootKeyHandle(commonSrkEquivalentHandle)
|
||||
var parent ParentKeyConfig
|
||||
if opts != nil && opts.Parent != nil {
|
||||
parent = *opts.Parent
|
||||
} else {
|
||||
parent = defaultParentConfig
|
||||
}
|
||||
srk, _, err := t.getStorageRootKeyHandle(parent)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get SRK handle: %v", err)
|
||||
}
|
||||
@ -287,7 +302,13 @@ func (t *wrappedTPM20) newKey(ak *AK, opts *KeyConfig) (*Key, error) {
|
||||
}
|
||||
|
||||
func createKey(t *wrappedTPM20, opts *KeyConfig) (tpmutil.Handle, []byte, []byte, []byte, error) {
|
||||
srk, _, err := t.getStorageRootKeyHandle(commonSrkEquivalentHandle)
|
||||
var parent ParentKeyConfig
|
||||
if opts != nil && opts.Parent != nil {
|
||||
parent = *opts.Parent
|
||||
} else {
|
||||
parent = defaultParentConfig
|
||||
}
|
||||
srk, _, err := t.getStorageRootKeyHandle(parent)
|
||||
if err != nil {
|
||||
return 0, nil, nil, nil, fmt.Errorf("failed to get SRK handle: %v", err)
|
||||
}
|
||||
@ -352,7 +373,7 @@ func templateFromConfig(opts *KeyConfig) (tpm2.Public, error) {
|
||||
return tmpl, nil
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte) (tpmutil.Handle, *serializedKey, error) {
|
||||
func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte, parent ParentKeyConfig) (tpmutil.Handle, *serializedKey, error) {
|
||||
sKey, err := deserializeKey(opaqueBlob, TPMVersion20)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("deserializeKey() failed: %v", err)
|
||||
@ -361,7 +382,7 @@ func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte) (tpmutil.Handle, *s
|
||||
return 0, nil, fmt.Errorf("unsupported key encoding: %x", sKey.Encoding)
|
||||
}
|
||||
|
||||
srk, _, err := t.getStorageRootKeyHandle(commonSrkEquivalentHandle)
|
||||
srk, _, err := t.getStorageRootKeyHandle(parent)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("failed to get SRK handle: %v", err)
|
||||
}
|
||||
@ -373,7 +394,11 @@ func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte) (tpmutil.Handle, *s
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) loadAK(opaqueBlob []byte) (*AK, error) {
|
||||
hnd, sKey, err := t.deserializeAndLoad(opaqueBlob)
|
||||
return t.loadAKWithParent(opaqueBlob, defaultParentConfig)
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) {
|
||||
hnd, sKey, err := t.deserializeAndLoad(opaqueBlob, parent)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot load attestation key: %v", err)
|
||||
}
|
||||
@ -381,7 +406,11 @@ func (t *wrappedTPM20) loadAK(opaqueBlob []byte) (*AK, error) {
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) loadKey(opaqueBlob []byte) (*Key, error) {
|
||||
hnd, sKey, err := t.deserializeAndLoad(opaqueBlob)
|
||||
return t.loadKeyWithParent(opaqueBlob, defaultParentConfig)
|
||||
}
|
||||
|
||||
func (t *wrappedTPM20) loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) {
|
||||
hnd, sKey, err := t.deserializeAndLoad(opaqueBlob, parent)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot load signing key: %v", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user