diff --git a/tpm2/export_test.go b/tpm2/export_test.go index 265655ec..95a08785 100644 --- a/tpm2/export_test.go +++ b/tpm2/export_test.go @@ -20,7 +20,11 @@ package tpm2 import ( + "errors" + "github.com/canonical/go-tpm2" + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" "github.com/snapcore/secboot" ) @@ -34,18 +38,18 @@ const ( // Export variables and unexported functions for testing var ( ComputeV0PinNVIndexPostInitAuthPolicies = computeV0PinNVIndexPostInitAuthPolicies - CreatePcrPolicyCounter = createPcrPolicyCounter + CreatePcrPolicyCounter = createPcrPolicyCounterLegacy + EnsurePcrPolicyCounter = ensurePcrPolicyCounter ComputeV1PcrPolicyRefFromCounterName = computeV1PcrPolicyRefFromCounterName ComputeV3PcrPolicyCounterAuthPolicies = computeV3PcrPolicyCounterAuthPolicies ComputeV3PcrPolicyRefFromCounterName = computeV3PcrPolicyRefFromCounterName ComputeSnapModelDigest = computeSnapModelDigest - DeriveAuthValue = deriveAuthValue DeriveV3PolicyAuthKey = deriveV3PolicyAuthKey ErrSessionDigestNotFound = errSessionDigestNotFound IsPolicyDataError = isPolicyDataError - MakeKeyData = makeKeyData - MakeKeyDataPolicy = makeKeyDataPolicy - MakeKeyDataWithPolicy = makeKeyDataWithPolicy + MakeSealedKeyData = makeSealedKeyData + MakeKeyDataNoAuth = makeKeyDataNoAuth + MakeKeyDataWithPassphraseConstructor = makeKeyDataWithPassphraseConstructor NewKeyData = newKeyData NewKeyDataPolicy = newKeyDataPolicy NewKeyDataPolicyLegacy = newKeyDataPolicyLegacy @@ -66,10 +70,10 @@ type KeyData_v0 = keyData_v0 type KeyData_v1 = keyData_v1 type KeyData_v2 = keyData_v2 type KeyData_v3 = keyData_v3 +type AdditionalData_v3 = additionalData_v3 type KeyDataError = keyDataError -type KeyDataParams = keyDataParams +type SealedKeyDataParams = makeSealedKeyDataParams type KeyDataPolicy = keyDataPolicy -type KeyDataPolicyParams = keyDataPolicyParams type KeyDataPolicy_v0 = keyDataPolicy_v0 type KeyDataPolicy_v1 = keyDataPolicy_v1 type KeyDataPolicy_v2 = keyDataPolicy_v2 @@ -182,15 +186,15 @@ func MakeMockPolicyPCRValuesFull(params []MockPolicyPCRParam) (out []tpm2.PCRVal return } -func MockCreatePcrPolicyCounter(fn func(*tpm2.TPMContext, tpm2.Handle, *tpm2.Public, tpm2.SessionContext) (*tpm2.NVPublic, uint64, error)) (restore func()) { - orig := createPcrPolicyCounter - createPcrPolicyCounter = fn +func MockEnsurePcrPolicyCounter(fn func(*tpm2.TPMContext, tpm2.Handle, *tpm2.Public, tpm2.SessionContext) (*tpm2.NVPublic, error)) (restore func()) { + orig := ensurePcrPolicyCounter + ensurePcrPolicyCounter = fn return func() { - createPcrPolicyCounter = orig + ensurePcrPolicyCounter = orig } } -func MockNewKeyDataPolicy(fn func(tpm2.HashAlgorithmId, *tpm2.Public, *tpm2.NVPublic, uint64) (KeyDataPolicy, tpm2.Digest, error)) (restore func()) { +func MockNewKeyDataPolicy(fn func(tpm2.HashAlgorithmId, *tpm2.Public, string, *tpm2.NVPublic, bool) (KeyDataPolicy, tpm2.Digest, error)) (restore func()) { orig := newKeyDataPolicy newKeyDataPolicy = fn return func() { @@ -214,24 +218,24 @@ func MockSecbootNewKeyData(fn func(*secboot.KeyParams) (*secboot.KeyData, error) } } -func MockSkdbUpdatePCRProtectionPolicyImpl(fn func(*sealedKeyDataBase, *tpm2.TPMContext, secboot.PrimaryKey, *tpm2.NVPublic, *PCRProtectionProfile, tpm2.SessionContext) error) (restore func()) { - orig := skdbUpdatePCRProtectionPolicyImpl - skdbUpdatePCRProtectionPolicyImpl = fn +func MockSecbootNewKeyDataWithPassphrase(fn func(*secboot.KeyWithPassphraseParams, string, secboot.KDF) (*secboot.KeyData, error)) (restore func()) { + orig := secbootNewKeyDataWithPassphrase + secbootNewKeyDataWithPassphrase = fn return func() { - skdbUpdatePCRProtectionPolicyImpl = orig + secbootNewKeyDataWithPassphrase = orig } } -func (k *SealedKeyData) Data() KeyData { - return k.data -} - -func (k *SealedKeyData) Validate(tpm *tpm2.TPMContext, authKey secboot.PrimaryKey, session tpm2.SessionContext) error { - if _, err := k.validateData(tpm, session); err != nil { - return err +func MockSkdbUpdatePCRProtectionPolicyNoValidate(fn func(*sealedKeyDataBase, *tpm2.TPMContext, secboot.PrimaryKey, *tpm2.NVPublic, *PCRProtectionProfile, bool, tpm2.SessionContext) error) (restore func()) { + orig := skdbUpdatePCRProtectionPolicyNoValidate + skdbUpdatePCRProtectionPolicyNoValidate = fn + return func() { + skdbUpdatePCRProtectionPolicyNoValidate = orig } +} - return k.data.Policy().ValidateAuthKey(authKey) +func (k *SealedKeyData) Data() KeyData { + return k.data } func (k *SealedKeyObject) Data() KeyData { @@ -239,19 +243,19 @@ func (k *SealedKeyObject) Data() KeyData { } func (k *SealedKeyObject) Validate(tpm *tpm2.TPMContext, authKey secboot.PrimaryKey, session tpm2.SessionContext) error { - if _, err := k.validateData(tpm, session); err != nil { + if _, err := k.validateData(tpm, "", session); err != nil { return err } return k.data.Policy().ValidateAuthKey(authKey) } -func (c *createdPcrPolicyCounter) TPM() *tpm2.TPMContext { - return c.tpm -} +func (k *SealedKeyData) Validate(tpm *tpm2.TPMContext, authKey secboot.PrimaryKey, session tpm2.SessionContext) error { + if _, err := k.validateData(tpm, "", session); err != nil { + return err + } -func (c *createdPcrPolicyCounter) Session() tpm2.SessionContext { - return c.session + return k.data.Policy().ValidateAuthKey(authKey) } func ValidateKeyDataFile(tpm *tpm2.TPMContext, keyFile string, authKey secboot.PrimaryKey, session tpm2.SessionContext) error { @@ -262,3 +266,26 @@ func ValidateKeyDataFile(tpm *tpm2.TPMContext, keyFile string, authKey secboot.P return k.Validate(tpm, authKey, session) } + +type protectedKeys struct { + Primary secboot.PrimaryKey + Unique []byte +} + +func UnmarshalProtectedKeys(data []byte) (*protectedKeys, error) { + s := cryptobyte.String(data) + if !s.ReadASN1(&s, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("malformed input") + } + + pk := new(protectedKeys) + + if !s.ReadASN1Bytes((*[]byte)(&pk.Primary), cryptobyte_asn1.OCTET_STRING) { + return nil, errors.New("malformed primary key") + } + if !s.ReadASN1Bytes(&pk.Unique, cryptobyte_asn1.OCTET_STRING) { + return nil, errors.New("malformed unique key") + } + + return pk, nil +} diff --git a/tpm2/platform_test.go b/tpm2/platform_test.go index 590dc787..4803aed0 100644 --- a/tpm2/platform_test.go +++ b/tpm2/platform_test.go @@ -20,12 +20,19 @@ package tpm2_test import ( + "crypto" "encoding/json" + gohash "hash" + "io" "math/rand" "os" "syscall" "github.com/canonical/go-tpm2" + "github.com/canonical/go-tpm2/util" + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" + "golang.org/x/crypto/hkdf" . "gopkg.in/check.v1" @@ -64,71 +71,41 @@ func (s *platformSuite) SetUpTest(c *C) { var _ = Suite(&platformSuite{}) -func (s *platformSuite) TestDeriveAuthValue(c *C) { - key := testutil.DecodeHexString(c, "eb3df724b267220a2ebf1ad93ca05c7ba7ab2b321f2e7fddbc9741882b274433290973b9f9ecb6a64396da33d717f7af") - expected := testutil.DecodeHexString(c, "874fcd20ed7c7071f6fd1d9ccb8ebc088c902712ba6cad7a14d7db71d75673b8") - - value, err := DeriveAuthValue(key, 32) - c.Check(err, IsNil) - c.Check(value, DeepEquals, expected) - c.Logf("%x", value) -} - -func (s *platformSuite) TestDeriveAuthValueDifferentLen(c *C) { - key := testutil.DecodeHexString(c, "eb3df724b267220a2ebf1ad93ca05c7ba7ab2b321f2e7fddbc9741882b274433290973b9f9ecb6a64396da33d717f7af") - expected := testutil.DecodeHexString(c, "874fcd20ed7c7071f6fd1d9ccb8ebc088c902712") - - value, err := DeriveAuthValue(key, 20) - c.Check(err, IsNil) - c.Check(value, DeepEquals, expected) - c.Logf("%x", value) -} - -func (s *platformSuite) TestDeriveAuthValueDifferentKey(c *C) { - key := testutil.DecodeHexString(c, "7facbeb6f2a7f233f68059da3f1d9c9706530eced4cca76ba1e1551f0e814c40ac2a076e208880ab6d2afe31f04e096a") - expected := testutil.DecodeHexString(c, "fc69c90fe401ed40906698fe290e6be07b8c7b8b5b42b6166044cf9e32b8e300") - - value, err := DeriveAuthValue(key, 32) - c.Check(err, IsNil) - c.Check(value, DeepEquals, expected) - c.Logf("%x", value) -} - func (s *platformSuite) TestRecoverKeysIntegrated(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, primaryKey, unlockKey, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) - keyUnsealed, authKeyUnsealed, err := k.RecoverKeys() + unlockKeyUnsealed, primaryKeyUnsealed, err := k.RecoverKeys() c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + c.Check(unlockKeyUnsealed, DeepEquals, unlockKey) + c.Check(primaryKeyUnsealed, DeepEquals, primaryKey) } func (s *platformSuite) TestRecoverKeysWithPassphraseIntegrated(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) - c.Assert(err, IsNil) + passphraseParams := &PassphraseProtectKeyParams{ + ProtectKeyParams: *params, + } var kdf testutil.MockKDF - c.Check(k.SetPassphrase("passphrase", nil, &kdf), IsNil) + k, primaryKey, unlockKey, err := NewTPMPassphraseProtectedKey(s.TPM(), passphraseParams, "passphrase", &kdf) + c.Assert(err, IsNil) - keyUnsealed, authKeyUnsealed, err := k.RecoverKeysWithPassphrase("passphrase", &kdf) + unlockKeyUnsealed, primaryKeyUnsealed, err := k.RecoverKeysWithPassphrase("passphrase", &kdf) c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + c.Check(unlockKeyUnsealed, DeepEquals, unlockKey) + c.Check(primaryKeyUnsealed, DeepEquals, primaryKey) } func (s *platformSuite) TestRecoverKeysWithBadPassphraseIntegrated(c *C) { @@ -137,87 +114,115 @@ func (s *platformSuite) TestRecoverKeysWithBadPassphraseIntegrated(c *C) { params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, _, err := ProtectKeyWithTPM(s.TPM(), key, params) - c.Assert(err, IsNil) + passphraseParams := &PassphraseProtectKeyParams{ + ProtectKeyParams: *params, + } var kdf testutil.MockKDF - c.Check(k.SetPassphrase("passphrase", nil, &kdf), IsNil) + k, _, _, err := NewTPMPassphraseProtectedKey(s.TPM(), passphraseParams, "passphrase", &kdf) + c.Assert(err, IsNil) _, _, err = k.RecoverKeysWithPassphrase("1234", &kdf) c.Check(err, Equals, secboot.ErrInvalidPassphrase) } func (s *platformSuite) TestChangePassphraseIntegrated(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) - c.Assert(err, IsNil) + passphraseParams := &PassphraseProtectKeyParams{ + ProtectKeyParams: *params, + } var kdf testutil.MockKDF - c.Check(k.SetPassphrase("passphrase", nil, &kdf), IsNil) + k, primaryKey, unlockKey, err := NewTPMPassphraseProtectedKey(s.TPM(), passphraseParams, "passphrase", &kdf) + c.Assert(err, IsNil) - c.Check(k.ChangePassphrase("passphrase", "1234", nil, &kdf), IsNil) + c.Check(k.ChangePassphrase("passphrase", "1234", &kdf), IsNil) - keyUnsealed, authKeyUnsealed, err := k.RecoverKeysWithPassphrase("1234", &kdf) + unlockKeyUnsealed, primaryKeyUnsealed, err := k.RecoverKeysWithPassphrase("1234", &kdf) c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + c.Check(unlockKeyUnsealed, DeepEquals, unlockKey) + c.Check(primaryKeyUnsealed, DeepEquals, primaryKey) } func (s *platformSuite) TestChangePassphraseWithBadPassphraseIntegrated(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) - c.Assert(err, IsNil) + passphraseParams := &PassphraseProtectKeyParams{ + ProtectKeyParams: *params, + } var kdf testutil.MockKDF - c.Check(k.SetPassphrase("passphrase", nil, &kdf), IsNil) + k, primaryKey, unlockKey, err := NewTPMPassphraseProtectedKey(s.TPM(), passphraseParams, "passphrase", &kdf) + c.Assert(err, IsNil) - c.Check(k.ChangePassphrase("1234", "1234", nil, &kdf), Equals, secboot.ErrInvalidPassphrase) + c.Check(k.ChangePassphrase("1234", "1234", &kdf), Equals, secboot.ErrInvalidPassphrase) - keyUnsealed, authKeyUnsealed, err := k.RecoverKeysWithPassphrase("passphrase", &kdf) + unlockKeyUnsealed, primaryKeyUnsealed, err := k.RecoverKeysWithPassphrase("passphrase", &kdf) c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + c.Check(unlockKeyUnsealed, DeepEquals, unlockKey) + c.Check(primaryKeyUnsealed, DeepEquals, primaryKey) } -func (s *platformSuite) testRecoverKeys(c *C, params *ProtectKeyParams) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) +func (s *platformSuite) verifyASN1(c *C, data []byte) (primaryKey, unique []byte) { + d := cryptobyte.String(data) + c.Assert(d.ReadASN1(&d, cryptobyte_asn1.SEQUENCE), Equals, true) + + primaryKey = make([]byte, 32) + unique = make([]byte, 32) + + c.Assert(d.ReadASN1Bytes(&primaryKey, cryptobyte_asn1.OCTET_STRING), Equals, true) + c.Assert(d.ReadASN1Bytes(&unique, cryptobyte_asn1.OCTET_STRING), Equals, true) - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + return primaryKey, unique +} + +func (s *platformSuite) testRecoverKeys(c *C, params *ProtectKeyParams) { + k, primaryKey, unlockKey, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) var platformHandle json.RawMessage c.Check(k.UnmarshalPlatformHandle(&platformHandle), IsNil) + platformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + AuthMode: k.AuthMode(), + } + var handler PlatformKeyDataHandler - payload, err := handler.RecoverKeys(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}) + payload, err := handler.RecoverKeys(platformKeyData, s.lastEncryptedPayload) + c.Assert(err, IsNil) - keyUnsealed, authKeyUnsealed, err := payload.Unmarshal() - c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + pk, u := s.verifyASN1(c, payload) + c.Check(primaryKey, DeepEquals, secboot.PrimaryKey(pk)) + + uk := make([]byte, len(pk)) + r := hkdf.New(func() gohash.Hash { return crypto.SHA256.New() }, pk, u, []byte("UNLOCK")) + _, err = io.ReadFull(r, uk) + c.Assert(err, IsNil) + c.Check(unlockKey, DeepEquals, secboot.DiskUnlockKey(uk)) } func (s *platformSuite) TestRecoverKeysSimplePCRProfile(c *C) { s.testRecoverKeys(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)}) + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + }) } func (s *platformSuite) TestRecoverKeysNilPCRProfile(c *C) { @@ -232,14 +237,13 @@ func (s *platformSuite) TestRecoverKeysNoPCRPolicyCounter(c *C) { } func (s *platformSuite) testRecoverKeysNoValidSRK(c *C, prepareSrk func()) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, primaryKey, unlockKey, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) prepareSrk() @@ -249,13 +253,19 @@ func (s *platformSuite) testRecoverKeysNoValidSRK(c *C, prepareSrk func()) { var handler PlatformKeyDataHandler payload, err := handler.RecoverKeys(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}) + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256)}, + s.lastEncryptedPayload) - keyUnsealed, authKeyUnsealed, err := payload.Unmarshal() - c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + pk, u := s.verifyASN1(c, payload) + c.Check(primaryKey, DeepEquals, secboot.PrimaryKey(pk)) + + uk := make([]byte, len(pk)) + r := hkdf.New(func() gohash.Hash { return crypto.SHA256.New() }, pk, u, []byte("UNLOCK")) + _, err = io.ReadFull(r, uk) + c.Assert(err, IsNil) + c.Check(unlockKey, DeepEquals, secboot.DiskUnlockKey(uk)) } func (s *platformSuite) TestRecoverKeysMissingSRK(c *C) { @@ -289,7 +299,7 @@ func (s *platformSuite) testRecoverKeysImportable(c *C, params *ProtectKeyParams key := make(secboot.DiskUnlockKey, 32) rand.Read(key) - k, authKey, err := ProtectKeyWithExternalStorageKey(srkPub, key, params) + k, primaryKey, unlockKey, err := NewExternalTPMProtectedKey(srkPub, params) c.Assert(err, IsNil) var platformHandle json.RawMessage @@ -297,13 +307,20 @@ func (s *platformSuite) testRecoverKeysImportable(c *C, params *ProtectKeyParams var handler PlatformKeyDataHandler payload, err := handler.RecoverKeys(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}) + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256)}, + s.lastEncryptedPayload) + c.Assert(err, IsNil) - keyUnsealed, authKeyUnsealed, err := payload.Unmarshal() - c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + pk, u := s.verifyASN1(c, payload) + c.Check(primaryKey, DeepEquals, secboot.PrimaryKey(pk)) + + uk := make([]byte, len(pk)) + r := hkdf.New(func() gohash.Hash { return crypto.SHA256.New() }, pk, u, []byte("UNLOCK")) + _, err = io.ReadFull(r, uk) + c.Assert(err, IsNil) + c.Check(unlockKey, DeepEquals, secboot.DiskUnlockKey(uk)) } func (s *platformSuite) TestRecoverKeysImportableSimplePCRProfile(c *C) { @@ -314,16 +331,19 @@ func (s *platformSuite) TestRecoverKeysImportableSimplePCRProfile(c *C) { func (s *platformSuite) TestRecoverKeysImportableNilPCRProfile(c *C) { s.testRecoverKeysImportable(c, &ProtectKeyParams{ - PCRPolicyCounterHandle: tpm2.HandleNull}) + PCRPolicyCounterHandle: tpm2.HandleNull, + Role: ""}) } func (s *platformSuite) TestRecoverKeysNoTPMConnection(c *C) { key := make(secboot.DiskUnlockKey, 32) rand.Read(key) - k, _, err := ProtectKeyWithTPM(s.TPM(), key, &ProtectKeyParams{ + k, _, _, err := NewTPMProtectedKey(s.TPM(), &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: tpm2.HandleNull}) + PCRPolicyCounterHandle: tpm2.HandleNull, + Role: "", + }) c.Check(err, IsNil) restore := tpm2test.MockOpenDefaultTctiFn(func() (tpm2.TCTI, error) { @@ -336,8 +356,10 @@ func (s *platformSuite) TestRecoverKeysNoTPMConnection(c *C) { var handler PlatformKeyDataHandler _, err = handler.RecoverKeys(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}) + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256)}, + s.lastEncryptedPayload) c.Assert(err, testutil.ConvertibleTo, &secboot.PlatformHandlerError{}) c.Check(err.(*secboot.PlatformHandlerError).Type, Equals, secboot.PlatformHandlerErrorUnavailable) c.Check(err, testutil.ErrorIs, ErrNoTPM2Device) @@ -345,25 +367,26 @@ func (s *platformSuite) TestRecoverKeysNoTPMConnection(c *C) { } func (s *platformSuite) testRecoverKeysUnsealErrorHandling(c *C, prepare func(*secboot.KeyData, secboot.PrimaryKey)) error { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, primaryKey, _, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) - prepare(k, authKey) + prepare(k, primaryKey) var platformHandle json.RawMessage c.Check(k.UnmarshalPlatformHandle(&platformHandle), IsNil) var handler PlatformKeyDataHandler _, err = handler.RecoverKeys(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}) + Version: k.Version(), + AuthMode: secboot.AuthModeNone, + Role: "", + KDFAlg: crypto.Hash(crypto.SHA256), + EncodedHandle: platformHandle}, + s.lastEncryptedPayload) return err } @@ -390,7 +413,7 @@ func (s *platformSuite) TestRecoverKeysUnsealErrorHandlingInvalidPCRProfile(c *C } func (s *platformSuite) TestRecoverKeysUnsealErrorHandlingRevokedPolicy(c *C) { - err := s.testRecoverKeysUnsealErrorHandling(c, func(k *secboot.KeyData, authKey secboot.PrimaryKey) { + err := s.testRecoverKeysUnsealErrorHandling(c, func(k *secboot.KeyData, primaryKey secboot.PrimaryKey) { w := newMockKeyDataWriter() c.Check(k.WriteAtomic(w), IsNil) @@ -399,8 +422,9 @@ func (s *platformSuite) TestRecoverKeysUnsealErrorHandlingRevokedPolicy(c *C) { skd, err := NewSealedKeyData(k2) c.Assert(err, IsNil) - c.Check(skd.UpdatePCRProtectionPolicy(s.TPM(), authKey, nil), IsNil) - c.Check(skd.RevokeOldPCRProtectionPolicies(s.TPM(), authKey), IsNil) + // Increment NV counter + c.Check(skd.UpdatePCRProtectionPolicy(s.TPM(), primaryKey, nil, true), IsNil) + c.Check(skd.RevokeOldPCRProtectionPolicies(s.TPM(), primaryKey), IsNil) }) c.Assert(err, testutil.ConvertibleTo, &secboot.PlatformHandlerError{}) c.Check(err.(*secboot.PlatformHandlerError).Type, Equals, secboot.PlatformHandlerErrorInvalidData) @@ -432,54 +456,148 @@ func (s *platformSuite) TestRecoverKeysUnsealErrorHandlingProvisioningError(c *C } func (s *platformSuite) TestRecoverKeysWithAuthKey(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) + + // Need to mock newKeyDataPolicy to force require an auth value when using NewTPMProtectedKey so that we don't + // have to use the passphrase APIs. + restore := MockNewKeyDataPolicy(func(alg tpm2.HashAlgorithmId, key *tpm2.Public, role string, pcrPolicyCounterPub *tpm2.NVPublic, requireAuthValue bool) (KeyDataPolicy, tpm2.Digest, error) { + index := tpm2.HandleNull + var indexName tpm2.Name + if pcrPolicyCounterPub != nil { + index = pcrPolicyCounterPub.Index + indexName = pcrPolicyCounterPub.Name() + } + + pcrPolicyRef := ComputeV3PcrPolicyRefFromCounterName(key.NameAlg, []byte(role), indexName) + + trial := util.ComputeAuthPolicy(alg) + trial.PolicyAuthorize(pcrPolicyRef, key.Name()) + trial.PolicyAuthValue() + + mockPolicyData := &KeyDataPolicy_v3{ + StaticData: &StaticPolicyData_v3{ + AuthPublicKey: key, + PCRPolicyRef: pcrPolicyRef, + PCRPolicyCounterHandle: index, + RequireAuthValue: true}, + PCRData: &PcrPolicyData_v3{ + AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgNull}, + }} + + mockPolicyDigest := trial.GetDigest() + + return mockPolicyData, mockPolicyDigest, nil + }) + defer restore() params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, primaryKey, unlockKey, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) var platformHandle json.RawMessage c.Check(k.UnmarshalPlatformHandle(&platformHandle), IsNil) + platformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + AuthMode: k.AuthMode(), + } + var handler PlatformKeyDataHandler - platformHandle, err = handler.ChangeAuthKey(platformHandle, nil, []byte{1, 2, 3, 4}) + newHandle, err := handler.ChangeAuthKey(platformKeyData, nil, []byte{1, 2, 3, 4}) c.Check(err, IsNil) - payload, err := handler.RecoverKeysWithAuthKey(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}, []byte{1, 2, 3, 4}) + newPlatformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: newHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + AuthMode: k.AuthMode(), + } - keyUnsealed, authKeyUnsealed, err := payload.Unmarshal() + payload, err := handler.RecoverKeysWithAuthKey(newPlatformKeyData, s.lastEncryptedPayload, []byte{1, 2, 3, 4}) c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + + pk, u := s.verifyASN1(c, payload) + c.Check(primaryKey, DeepEquals, secboot.PrimaryKey(pk)) + + uk := make([]byte, len(pk)) + r := hkdf.New(func() gohash.Hash { return crypto.SHA256.New() }, pk, u, []byte("UNLOCK")) + _, err = io.ReadFull(r, uk) + c.Assert(err, IsNil) + c.Check(unlockKey, DeepEquals, secboot.DiskUnlockKey(uk)) } func (s *platformSuite) TestRecoverKeysWithIncorrectAuthKey(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) + + // Need to mock newKeyDataPolicy to force require an auth value when using NewTPMProtectedKey so that we don't + // have to use the passphrase APIs. + restore := MockNewKeyDataPolicy(func(alg tpm2.HashAlgorithmId, key *tpm2.Public, role string, pcrPolicyCounterPub *tpm2.NVPublic, requireAuthValue bool) (KeyDataPolicy, tpm2.Digest, error) { + index := tpm2.HandleNull + var indexName tpm2.Name + if pcrPolicyCounterPub != nil { + index = pcrPolicyCounterPub.Index + indexName = pcrPolicyCounterPub.Name() + } + + pcrPolicyRef := ComputeV3PcrPolicyRefFromCounterName(key.NameAlg, []byte(role), indexName) + + trial := util.ComputeAuthPolicy(alg) + trial.PolicyAuthorize(pcrPolicyRef, key.Name()) + trial.PolicyAuthValue() + + mockPolicyData := &KeyDataPolicy_v3{ + StaticData: &StaticPolicyData_v3{ + AuthPublicKey: key, + PCRPolicyRef: pcrPolicyRef, + PCRPolicyCounterHandle: index, + RequireAuthValue: true}, + PCRData: &PcrPolicyData_v3{ + AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgNull}, + }} + + mockPolicyDigest := trial.GetDigest() + + return mockPolicyData, mockPolicyDigest, nil + }) + defer restore() params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, _, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, _, _, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) var platformHandle json.RawMessage c.Check(k.UnmarshalPlatformHandle(&platformHandle), IsNil) + platformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + AuthMode: k.AuthMode(), + } + var handler PlatformKeyDataHandler - platformHandle, err = handler.ChangeAuthKey(platformHandle, nil, []byte{1, 2, 3, 4}) + newHandle, err := handler.ChangeAuthKey(platformKeyData, nil, []byte{1, 2, 3, 4}) c.Check(err, IsNil) - _, err = handler.RecoverKeysWithAuthKey(&secboot.PlatformKeyData{ - EncodedHandle: platformHandle, - EncryptedPayload: s.lastEncryptedPayload}, []byte{5, 6, 7, 8}) + newPlatformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: newHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + // AuthMode: k.AuthMode(), + AuthMode: secboot.AuthModePassphrase, + } + + _, err = handler.RecoverKeysWithAuthKey(newPlatformKeyData, s.lastEncryptedPayload, []byte{5, 6, 7, 8}) c.Assert(err, testutil.ConvertibleTo, &secboot.PlatformHandlerError{}) c.Check(err.(*secboot.PlatformHandlerError).Type, Equals, secboot.PlatformHandlerErrorInvalidAuthKey) c.Check(err, ErrorMatches, "cannot unseal key: TPM returned an error for session 1 whilst executing command TPM_CC_Unseal: "+ @@ -487,24 +605,70 @@ func (s *platformSuite) TestRecoverKeysWithIncorrectAuthKey(c *C) { } func (s *platformSuite) TestChangeAuthKeyWithIncorrectAuthKey(c *C) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) + + // Need to mock newKeyDataPolicy to force require an auth value when using NewTPMProtectedKey so that we don't + // have to use the passphrase APIs. + restore := MockNewKeyDataPolicy(func(alg tpm2.HashAlgorithmId, key *tpm2.Public, role string, pcrPolicyCounterPub *tpm2.NVPublic, requireAuthValue bool) (KeyDataPolicy, tpm2.Digest, error) { + index := tpm2.HandleNull + var indexName tpm2.Name + if pcrPolicyCounterPub != nil { + index = pcrPolicyCounterPub.Index + indexName = pcrPolicyCounterPub.Name() + } + + pcrPolicyRef := ComputeV3PcrPolicyRefFromCounterName(key.NameAlg, []byte(role), indexName) + + trial := util.ComputeAuthPolicy(alg) + trial.PolicyAuthorize(pcrPolicyRef, key.Name()) + trial.PolicyAuthValue() + + mockPolicyData := &KeyDataPolicy_v3{ + StaticData: &StaticPolicyData_v3{ + AuthPublicKey: key, + PCRPolicyRef: pcrPolicyRef, + PCRPolicyCounterHandle: index, + RequireAuthValue: true}, + PCRData: &PcrPolicyData_v3{ + AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgNull}, + }} + + mockPolicyDigest := trial.GetDigest() + + return mockPolicyData, mockPolicyDigest, nil + }) + defer restore() params := &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0)} + PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), + Role: "", + } - k, _, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, _, _, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) var platformHandle json.RawMessage c.Check(k.UnmarshalPlatformHandle(&platformHandle), IsNil) + platformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: platformHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + AuthMode: k.AuthMode(), + } + var handler PlatformKeyDataHandler - platformHandle, err = handler.ChangeAuthKey(platformHandle, nil, []byte{1, 2, 3, 4}) + newHandle, err := handler.ChangeAuthKey(platformKeyData, nil, []byte{1, 2, 3, 4}) c.Check(err, IsNil) - _, err = handler.ChangeAuthKey(platformHandle, nil, []byte{5, 6, 7, 8}) + newPlatformKeyData := &secboot.PlatformKeyData{ + Version: k.Version(), + EncodedHandle: newHandle, + KDFAlg: crypto.Hash(crypto.SHA256), + AuthMode: k.AuthMode(), + } + + _, err = handler.ChangeAuthKey(newPlatformKeyData, nil, []byte{5, 6, 7, 8}) c.Assert(err, testutil.ConvertibleTo, &secboot.PlatformHandlerError{}) c.Check(err.(*secboot.PlatformHandlerError).Type, Equals, secboot.PlatformHandlerErrorInvalidAuthKey) c.Check(err, ErrorMatches, "TPM returned an error for session 1 whilst executing command TPM_CC_ObjectChangeAuth: "+ diff --git a/tpm2/policy_test.go b/tpm2/policy_test.go index 030fc476..ea59afc7 100644 --- a/tpm2/policy_test.go +++ b/tpm2/policy_test.go @@ -228,7 +228,7 @@ func (s *policySuiteNoTPM) testNewKeyDataPolicy(c *C, data *testNewKeyDataPolicy pcrPolicyCounterHandle = data.pcrPolicyCounterPub.Index } - policy, digest, err := NewKeyDataPolicy(data.alg, authKey, data.pcrPolicyCounterPub, data.pcrPolicySequence) + policy, digest, err := NewKeyDataPolicy(data.alg, authKey, "", data.pcrPolicyCounterPub, false) c.Assert(err, IsNil) c.Assert(policy, testutil.ConvertibleTo, &KeyDataPolicy_v3{}) c.Check(policy.(*KeyDataPolicy_v3).StaticData.AuthPublicKey, DeepEquals, authKey) @@ -251,8 +251,8 @@ xtjPyepMPNg3K7iPmPopFLA5Ap8RjR1Eu9B8LllUHTqYHJY6YQ3o+CP5TQ== NameAlg: tpm2.HashAlgorithmSHA256, Attrs: tpm2.NVTypeCounter.WithAttrs(tpm2.AttrNVPolicyWrite | tpm2.AttrNVAuthRead | tpm2.AttrNVNoDA | tpm2.AttrNVWritten), Size: 8}, - pcrPolicySequence: 10, - expected: testutil.DecodeHexString(c, "61f5396bcbd2bd3ed1392edaf88314da1230f6f252962c704119659295eca112")}) + pcrPolicySequence: 0, + expected: testutil.DecodeHexString(c, "aaf8226b1df9aefc9d03533b58abaf514b0f4ab6c10af0e26ef5d9db0d8aff24")}) } func (s *policySuiteNoTPM) TestNewKeyDataPolicySHA1(c *C) { @@ -268,8 +268,8 @@ xtjPyepMPNg3K7iPmPopFLA5Ap8RjR1Eu9B8LllUHTqYHJY6YQ3o+CP5TQ== NameAlg: tpm2.HashAlgorithmSHA256, Attrs: tpm2.NVTypeCounter.WithAttrs(tpm2.AttrNVPolicyWrite | tpm2.AttrNVAuthRead | tpm2.AttrNVNoDA | tpm2.AttrNVWritten), Size: 8}, - pcrPolicySequence: 10, - expected: testutil.DecodeHexString(c, "1a1afefb96937bd752a24cc23dbc16ecde3c8268")}) + pcrPolicySequence: 0, + expected: testutil.DecodeHexString(c, "9a9aeb1e55e96cbae4cba7bc798046cc82ff669f")}) } func (s *policySuiteNoTPM) TestNewKeyDataPolicyNoPCRPolicyCounterHandle(c *C) { @@ -280,7 +280,7 @@ func (s *policySuiteNoTPM) TestNewKeyDataPolicyNoPCRPolicyCounterHandle(c *C) { MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE49+rltJgmI3V7QqrkLBpB4V3xunW xtjPyepMPNg3K7iPmPopFLA5Ap8RjR1Eu9B8LllUHTqYHJY6YQ3o+CP5TQ== -----END PUBLIC KEY-----`, - expected: testutil.DecodeHexString(c, "2171bcd975facbf5bf0ac504e2e9812d3cf5583c0162f96c849dd9b8154f4dc0")}) + expected: testutil.DecodeHexString(c, "9cac9314ff38f2cdf8c876b57d344657e76996ea872925acd95abec805165c31")}) } func (s *policySuiteNoTPM) TestNewKeyDataPolicyDifferentInitialSequence(c *C) { @@ -296,8 +296,8 @@ xtjPyepMPNg3K7iPmPopFLA5Ap8RjR1Eu9B8LllUHTqYHJY6YQ3o+CP5TQ== NameAlg: tpm2.HashAlgorithmSHA256, Attrs: tpm2.NVTypeCounter.WithAttrs(tpm2.AttrNVPolicyWrite | tpm2.AttrNVAuthRead | tpm2.AttrNVNoDA | tpm2.AttrNVWritten), Size: 8}, - pcrPolicySequence: 3000, - expected: testutil.DecodeHexString(c, "61f5396bcbd2bd3ed1392edaf88314da1230f6f252962c704119659295eca112")}) + pcrPolicySequence: 0, + expected: testutil.DecodeHexString(c, "aaf8226b1df9aefc9d03533b58abaf514b0f4ab6c10af0e26ef5d9db0d8aff24")}) } type testNewKeyDataPolicyLegacyData struct { diff --git a/tpm2/policy_v3_test.go b/tpm2/policy_v3_test.go index 5a173e4b..685a53d5 100644 --- a/tpm2/policy_v3_test.go +++ b/tpm2/policy_v3_test.go @@ -112,7 +112,7 @@ func (s *policyV3SuiteNoTPM) TestPCRPolicySequence(c *C) { type testV3UpdatePCRPolicyData struct { policyCounterHandle tpm2.Handle authKeyNameAlg tpm2.HashAlgorithmId - initialSeq uint64 + expectedCount uint64 alg tpm2.HashAlgorithmId pcrs tpm2.PCRSelectionList @@ -141,10 +141,9 @@ func (s *policyV3SuiteNoTPM) testUpdatePCRPolicy(c *C, data *testV3UpdatePCRPoli var policyData KeyDataPolicy = &KeyDataPolicy_v3{ StaticData: &StaticPolicyData_v3{ AuthPublicKey: authPublicKey}, - PCRData: &PcrPolicyData_v3{ - PolicySequence: data.initialSeq}} + } - params := NewPcrPolicyParams(key, data.pcrs, data.pcrDigests, policyCounterName) + params := NewPcrPolicyParams(key, data.pcrs, data.pcrDigests, policyCounterName, 1) c.Check(policyData.UpdatePCRPolicy(data.alg, params), IsNil) c.Check(policyData.(*KeyDataPolicy_v3).PCRData.Selection, tpm2_testutil.TPMValueDeepEquals, data.pcrs) @@ -159,7 +158,7 @@ func (s *policyV3SuiteNoTPM) testUpdatePCRPolicy(c *C, data *testV3UpdatePCRPoli } s.checkPolicyOrTree(c, data.alg, digests, orTree) - c.Check(policyData.(*KeyDataPolicy_v3).PCRData.PolicySequence, Equals, data.initialSeq+1) + c.Check(policyData.(*KeyDataPolicy_v3).PCRData.PolicySequence, Equals, data.expectedCount) c.Check(policyData.(*KeyDataPolicy_v3).PCRData.AuthorizedPolicy, DeepEquals, data.expectedPolicy) @@ -168,7 +167,7 @@ func (s *policyV3SuiteNoTPM) testUpdatePCRPolicy(c *C, data *testV3UpdatePCRPoli digest, err := util.ComputePolicyAuthorizeDigest(data.authKeyNameAlg, policyData.(*KeyDataPolicy_v3).PCRData.AuthorizedPolicy, - ComputeV3PcrPolicyRefFromCounterName(policyCounterName)) + policyData.(*KeyDataPolicy_v3).StaticData.PCRPolicyRef) c.Check(err, IsNil) ok, err := util.VerifySignature(authPublicKey.Public(), digest, policyData.(*KeyDataPolicy_v3).PCRData.AuthorizedPolicySignature) c.Check(err, IsNil) @@ -179,18 +178,18 @@ func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicy(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA256, "1")}, - expectedPolicy: testutil.DecodeHexString(c, "70affe6f1ca3f4bee098b50fc474d8e247adcf5bc54b1bd6fe356104c2641a8b")}) + expectedPolicy: testutil.DecodeHexString(c, "214063f761968beacf47ed3cfa692480aaba7981e3a4f95f606da88cc45182f3")}) } func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyDepth1(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{ @@ -199,17 +198,17 @@ func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyDepth1(c *C) { hash(crypto.SHA256, "3"), hash(crypto.SHA256, "4"), hash(crypto.SHA256, "5")}, - expectedPolicy: testutil.DecodeHexString(c, "96eb06bc20faa6dbfa138b644a33470e92176db65b373577fe0e92f5518a5693")}) + expectedPolicy: testutil.DecodeHexString(c, "0ced4fca4da1c7a3c7342e37a7e5c0f40a9c4d19d53eb3c4c63371fba54e4bac")}) } func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyDepth2(c *C) { data := &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, - expectedPolicy: testutil.DecodeHexString(c, "3dbd5e8007fe9a181b38f489da1577a71c2a049fd9d540f04bee5ed760621d36")} + expectedPolicy: testutil.DecodeHexString(c, "e51cd2aa2f8f6b872c2f3e3e98f6093591928af6deeaceae191e5b3ade3290f1")} for i := 1; i < 26; i++ { data.pcrDigests = append(data.pcrDigests, hash(crypto.SHA256, strconv.Itoa(i))) } @@ -220,18 +219,18 @@ func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyDifferentCounter(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x0180ffff, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA256, "1")}, - expectedPolicy: testutil.DecodeHexString(c, "dd3b263babcfaa7316376889c917587b4586fea8096de29dc3360611a887e835")}) + expectedPolicy: testutil.DecodeHexString(c, "e08a219a6a7fdbaf52e64f9f3fb7208948ed3994997be53cc79be4464bd6405f")}) } func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyNoCounter(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: tpm2.HandleNull, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 0, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA256, "1")}, @@ -242,44 +241,44 @@ func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicySHA1AuthKey(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA1, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA256, "1")}, - expectedPolicy: testutil.DecodeHexString(c, "70affe6f1ca3f4bee098b50fc474d8e247adcf5bc54b1bd6fe356104c2641a8b")}) + expectedPolicy: testutil.DecodeHexString(c, "214063f761968beacf47ed3cfa692480aaba7981e3a4f95f606da88cc45182f3")}) } func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyDifferentSequence(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 9999, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA256, "1")}, - expectedPolicy: testutil.DecodeHexString(c, "abc59e04a533674dc796b6bc51276a5fac18fed2177ab99a87e8a636c83bc8cc")}) + expectedPolicy: testutil.DecodeHexString(c, "214063f761968beacf47ed3cfa692480aaba7981e3a4f95f606da88cc45182f3")}) } func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicySHA1Policy(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA1, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA1, "1")}, - expectedPolicy: testutil.DecodeHexString(c, "10d3874da9f0605876695f76efa0bfbf1ea57f16")}) + expectedPolicy: testutil.DecodeHexString(c, "e537ec1e4b1d4ec5bae9a3644194e8d1a9181bf1")}) } func (s *policyV3SuiteNoTPM) TestUpdatePCRPolicyDifferentPCRs(c *C) { s.testUpdatePCRPolicy(c, &testV3UpdatePCRPolicyData{ policyCounterHandle: 0x01800000, authKeyNameAlg: tpm2.HashAlgorithmSHA256, - initialSeq: 1000, + expectedCount: 1, alg: tpm2.HashAlgorithmSHA256, pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA1, Select: []int{4, 7, 12}}}, pcrDigests: tpm2.DigestList{hash(crypto.SHA256, "1")}, - expectedPolicy: testutil.DecodeHexString(c, "a4569fcb0e2c2f1a6651c53e00c526c383c108edb3142339e6fad9d6ae5a488c")}) + expectedPolicy: testutil.DecodeHexString(c, "ce6e3eb8ecd88ef2e21327ad58c77b21a8b563b5b373f1eab08dcc8296c6ee56")}) } func (s *policyV3SuiteNoTPM) TestSetPCRPolicyFrom(c *C) { @@ -295,13 +294,12 @@ func (s *policyV3SuiteNoTPM) TestSetPCRPolicyFrom(c *C) { policyData1 := &KeyDataPolicy_v3{ StaticData: &StaticPolicyData_v3{ AuthPublicKey: s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, key)}, - PCRData: &PcrPolicyData_v3{ - PolicySequence: 5000}} + } params := NewPcrPolicyParams(key, tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{4, 7, 12}}}, tpm2.DigestList{hash(crypto.SHA256, "1"), hash(crypto.SHA256, "2")}, - policyCounterPub.Name()) + policyCounterPub.Name(), 5000) c.Check(policyData1.UpdatePCRPolicy(tpm2.HashAlgorithmSHA256, params), IsNil) var policyData2 KeyDataPolicy = &KeyDataPolicy_v3{ @@ -324,32 +322,40 @@ type testV3ExecutePCRPolicyData struct { } func (s *policyV3Suite) testExecutePCRPolicy(c *C, data *testV3ExecutePCRPolicyData) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) - authKeyPublic := s.newPolicyAuthPublicKey(c, data.authKeyNameAlg, authKey) + authKeyPublic := s.newPolicyAuthPublicKey(c, data.authKeyNameAlg, primaryKey) var policyCounterPub *tpm2.NVPublic - var policyCount uint64 var policyCounterName tpm2.Name if data.policyCounterHandle != tpm2.HandleNull { var err error - policyCounterPub, policyCount, err = CreatePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, data.policyCounterHandle), authKeyPublic, s.TPM().HmacSession()) + policyCounterPub, err = EnsurePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, data.policyCounterHandle), authKeyPublic, s.TPM().HmacSession()) c.Assert(err, IsNil) policyCounterName = policyCounterPub.Name() } - policyData, expectedDigest, err := NewKeyDataPolicy(data.alg, authKeyPublic, policyCounterPub, policyCount) + policyData, expectedDigest, err := NewKeyDataPolicy(data.alg, authKeyPublic, "", policyCounterPub, false) c.Assert(err, IsNil) c.Assert(policyData, testutil.ConvertibleTo, &KeyDataPolicy_v3{}) + var policyCount uint64 + if data.policyCounterHandle != tpm2.HandleNull { + context, err := policyData.PCRPolicyCounterContext(s.TPM().TPMContext, policyCounterPub, s.TPM().HmacSession()) + c.Assert(err, IsNil) + + policyCount, err = context.Get() + c.Assert(err, IsNil) + } + var digests tpm2.DigestList for _, v := range data.pcrValues { d, _ := util.ComputePCRDigest(data.alg, data.pcrs, v) digests = append(digests, d) } - params := NewPcrPolicyParams(authKey, data.pcrs, digests, policyCounterName) + params := NewPcrPolicyParams(primaryKey, data.pcrs, digests, policyCounterName, policyCount) c.Check(policyData.UpdatePCRPolicy(data.alg, params), IsNil) for _, selection := range data.pcrs { @@ -675,36 +681,44 @@ type testV3ExecutePCRPolicyErrorHandlingData struct { pcrEvents []pcrEvent - fn func(data *KeyDataPolicy_v3, authKey secboot.PrimaryKey) + fn func(data *KeyDataPolicy_v3, primaryKey secboot.PrimaryKey) } func (s *policyV3Suite) testExecutePCRPolicyErrorHandling(c *C, data *testV3ExecutePCRPolicyErrorHandlingData) error { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) - authKeyPublic := s.newPolicyAuthPublicKey(c, data.authKeyNameAlg, authKey) + authKeyPublic := s.newPolicyAuthPublicKey(c, data.authKeyNameAlg, primaryKey) var policyCounterPub *tpm2.NVPublic - var policyCount uint64 var policyCounterName tpm2.Name if data.policyCounterHandle != tpm2.HandleNull { var err error - policyCounterPub, policyCount, err = CreatePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, data.policyCounterHandle), authKeyPublic, s.TPM().HmacSession()) + policyCounterPub, err = EnsurePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, data.policyCounterHandle), authKeyPublic, s.TPM().HmacSession()) c.Assert(err, IsNil) policyCounterName = policyCounterPub.Name() } - policyData, expectedDigest, err := NewKeyDataPolicy(data.alg, authKeyPublic, policyCounterPub, policyCount) + policyData, expectedDigest, err := NewKeyDataPolicy(data.alg, authKeyPublic, "", policyCounterPub, false) c.Assert(err, IsNil) c.Assert(policyData, testutil.ConvertibleTo, &KeyDataPolicy_v3{}) + var policyCount uint64 + if data.policyCounterHandle != tpm2.HandleNull { + context, err := policyData.PCRPolicyCounterContext(s.TPM().TPMContext, policyCounterPub, s.TPM().HmacSession()) + c.Assert(err, IsNil) + + policyCount, err = context.Get() + c.Assert(err, IsNil) + } + var digests tpm2.DigestList for _, v := range data.pcrValues { d, _ := util.ComputePCRDigest(data.alg, data.pcrs, v) digests = append(digests, d) } - params := NewPcrPolicyParams(authKey, data.pcrs, digests, policyCounterName) + params := NewPcrPolicyParams(primaryKey, data.pcrs, digests, policyCounterName, policyCount) c.Check(policyData.UpdatePCRPolicy(data.alg, params), IsNil) for _, selection := range data.pcrs { @@ -718,7 +732,7 @@ func (s *policyV3Suite) testExecutePCRPolicyErrorHandling(c *C, data *testV3Exec c.Check(err, IsNil) } - data.fn(policyData.(*KeyDataPolicy_v3), authKey) + data.fn(policyData.(*KeyDataPolicy_v3), primaryKey) session := s.StartAuthSession(c, nil, nil, tpm2.SessionTypePolicy, nil, data.alg) executeErr := policyData.ExecutePCRPolicy(s.TPM().TPMContext, session, s.TPM().HmacSession()) @@ -1202,24 +1216,34 @@ func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingInvalidPCRPolicyCounter }, }) c.Check(IsPolicyDataError(err), testutil.IsTrue) - c.Check(err, ErrorMatches, "cannot verify PCR policy signature: TPM returned an error for parameter 2 whilst executing command TPM_CC_VerifySignature: TPM_RC_SIGNATURE \\(the signature is not valid\\)") + c.Check(err, ErrorMatches, "the PCR policy is invalid") } func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingRevoked(c *C) { // Test with a revoked PCR policy. + alg := tpm2.HashAlgorithmSHA256 + pcrs := tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{16, 23}}} + pcrValues := []tpm2.PCRValues{ + { + tpm2.HashAlgorithmSHA256: { + 16: tpm2test.MakePCRValueFromEvents(tpm2.HashAlgorithmSHA256, "foo", "bar"), + 23: tpm2test.MakePCRValueFromEvents(tpm2.HashAlgorithmSHA256, "bar", "foo"), + }, + }, + } + + var digests tpm2.DigestList + for _, v := range pcrValues { + d, _ := util.ComputePCRDigest(alg, pcrs, v) + digests = append(digests, d) + } + err := s.testExecutePCRPolicyErrorHandling(c, &testV3ExecutePCRPolicyErrorHandlingData{ - authKeyNameAlg: tpm2.HashAlgorithmSHA256, + authKeyNameAlg: alg, policyCounterHandle: 0x01800000, alg: tpm2.HashAlgorithmSHA256, - pcrs: tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{16, 23}}}, - pcrValues: []tpm2.PCRValues{ - { - tpm2.HashAlgorithmSHA256: { - 16: tpm2test.MakePCRValueFromEvents(tpm2.HashAlgorithmSHA256, "foo", "bar"), - 23: tpm2test.MakePCRValueFromEvents(tpm2.HashAlgorithmSHA256, "bar", "foo"), - }, - }, - }, + pcrs: pcrs, + pcrValues: pcrValues, pcrEvents: []pcrEvent{ { index: 16, @@ -1238,12 +1262,20 @@ func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingRevoked(c *C) { data: "foo", }, }, - fn: func(data *KeyDataPolicy_v3, authKey secboot.PrimaryKey) { + fn: func(data *KeyDataPolicy_v3, primaryKey secboot.PrimaryKey) { pub, _, err := s.TPM().NVReadPublic(tpm2.CreatePartialHandleContext(data.StaticData.PCRPolicyCounterHandle)) c.Assert(err, IsNil) target := data.PCRData.PolicySequence + authKeyPublic := s.newPolicyAuthPublicKey(c, alg, primaryKey) + policyCounterPub, err := EnsurePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, 0x01800000), authKeyPublic, s.TPM().HmacSession()) + c.Assert(err, IsNil) + policyCounterName := policyCounterPub.Name() + + params := NewPcrPolicyParams(primaryKey, pcrs, digests, policyCounterName, target+1) + data.UpdatePCRPolicy(alg, params) + context, err := data.PCRPolicyCounterContext(s.TPM().TPMContext, pub, s.TPM().HmacSession()) c.Assert(err, IsNil) for { @@ -1254,12 +1286,12 @@ func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingRevoked(c *C) { break } - c.Assert(context.Increment(authKey), IsNil) + c.Assert(context.Increment(primaryKey), IsNil) } }, }) c.Check(IsPolicyDataError(err), testutil.IsTrue) - c.Check(err, ErrorMatches, "the PCR policy has been revoked") + c.Check(err, ErrorMatches, "the PCR policy is invalid") } func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingInvalidAuthPublicKey(c *C) { @@ -1390,7 +1422,7 @@ func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingInvalidAuthorizedPolicy Details: &tpm2.SigSchemeU{ ECDSA: &tpm2.SigSchemeECDSA{ HashAlg: data.StaticData.AuthPublicKey.NameAlg}}} - _, signature, err := util.PolicyAuthorize(key, scheme, data.PCRData.AuthorizedPolicy, ComputeV3PcrPolicyRefFromCounterName(nil)) + _, signature, err := util.PolicyAuthorize(key, scheme, data.PCRData.AuthorizedPolicy, ComputeV3PcrPolicyRefFromCounterName(tpm2.HashAlgorithmSHA256, []byte(""), nil)) c.Assert(err, IsNil) data.PCRData.AuthorizedPolicySignature = signature }, @@ -1398,12 +1430,12 @@ func (s *policyV3Suite) TestExecutePCRPolicyErrorHandlingInvalidAuthorizedPolicy c.Check(err, IsNil) } -func (s *policyV3Suite) TestPolicyCounterContextGet(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, authKey) +func (s *policyV3Suite) TestPolicyCounterContextGetAndIncrement(c *C) { + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) + authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, primaryKey) - policyCounterPub, policyCount, err := CreatePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, 0x01800000), authKeyPublic, s.TPM().HmacSession()) + policyCounterPub, err := EnsurePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, 0x01800000), authKeyPublic, s.TPM().HmacSession()) c.Assert(err, IsNil) data := &KeyDataPolicy_v3{ @@ -1416,55 +1448,38 @@ func (s *policyV3Suite) TestPolicyCounterContextGet(c *C) { count, err := context.Get() c.Check(err, IsNil) - c.Check(count, Equals, policyCount) -} - -func (s *policyV3Suite) TestPolicyCounterContextIncrement(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, authKey) - - policyCounterPub, policyCount, err := CreatePcrPolicyCounter(s.TPM().TPMContext, s.NextAvailableHandle(c, 0x01800000), authKeyPublic, s.TPM().HmacSession()) - c.Assert(err, IsNil) - - data := &KeyDataPolicy_v3{ - StaticData: &StaticPolicyData_v3{ - AuthPublicKey: authKeyPublic, - PCRPolicyCounterHandle: policyCounterPub.Index}} + c.Check(count, Equals, uint64(1)) - context, err := data.PCRPolicyCounterContext(s.TPM().TPMContext, policyCounterPub, s.TPM().HmacSession()) - c.Assert(err, IsNil) - - c.Check(context.Increment(authKey), IsNil) + c.Check(context.Increment(primaryKey), IsNil) - count, err := context.Get() + count, err = context.Get() c.Check(err, IsNil) - c.Check(count, Equals, policyCount+1) + c.Check(count, Equals, uint64(2)) } func (s *policyV3SuiteNoTPM) TestValidateAuthKey(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, authKey) + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) + authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, primaryKey) data := &KeyDataPolicy_v3{ StaticData: &StaticPolicyData_v3{ AuthPublicKey: authKeyPublic}} - c.Check(data.ValidateAuthKey(authKey), IsNil) + c.Check(data.ValidateAuthKey(primaryKey), IsNil) } func (s *policyV3SuiteNoTPM) TestValidateAuthKeyWrongKey(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, authKey) + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) + authKeyPublic := s.newPolicyAuthPublicKey(c, tpm2.HashAlgorithmSHA256, primaryKey) data := &KeyDataPolicy_v3{ StaticData: &StaticPolicyData_v3{ AuthPublicKey: authKeyPublic}} - rand.Read(authKey) + rand.Read(primaryKey) - err := data.ValidateAuthKey(authKey) + err := data.ValidateAuthKey(primaryKey) c.Check(IsPolicyDataError(err), testutil.IsTrue) c.Check(err, ErrorMatches, "dynamic authorization policy signing private key doesn't match public key") } diff --git a/tpm2/seal.go b/tpm2/seal.go index 79a87811..d3c6a158 100644 --- a/tpm2/seal.go +++ b/tpm2/seal.go @@ -100,16 +100,16 @@ func makeKeyDataWithPassphraseConstructor(kdfOptions *secboot.KDFOptions, passph } type makeSealedKeyDataParams struct { - pcrProfile *PCRProtectionProfile - role string - pcrPolicyCounterHandle tpm2.Handle - primaryKey secboot.PrimaryKey - authMode secboot.AuthMode + PcrProfile *PCRProtectionProfile + Role string + PcrPolicyCounterHandle tpm2.Handle + PrimaryKey secboot.PrimaryKey + AuthMode secboot.AuthMode } func makeSealedKeyData(tpm *tpm2.TPMContext, params *makeSealedKeyDataParams, sealer keySealer, constructor keyDataConstructor, session tpm2.SessionContext) (*secboot.KeyData, secboot.PrimaryKey, secboot.DiskUnlockKey, error) { // Create a primary key, if required. - primaryKey := params.primaryKey + primaryKey := params.PrimaryKey if primaryKey == nil { primaryKey = make(secboot.PrimaryKey, 32) if _, err := rand.Read(primaryKey); err != nil { @@ -125,16 +125,16 @@ func makeSealedKeyData(tpm *tpm2.TPMContext, params *makeSealedKeyDataParams, se // Create PCR policy counter, if requested and if one doesn't already exist. var pcrPolicyCounterPub *tpm2.NVPublic - if params.pcrPolicyCounterHandle != tpm2.HandleNull { + if params.PcrPolicyCounterHandle != tpm2.HandleNull { if tpm == nil { return nil, nil, nil, errors.New("cannot create a PCR policy counter without a TPM connection") } var err error - pcrPolicyCounterPub, err = ensurePcrPolicyCounter(tpm, params.pcrPolicyCounterHandle, authPublicKey, session) + pcrPolicyCounterPub, err = ensurePcrPolicyCounter(tpm, params.PcrPolicyCounterHandle, authPublicKey, session) switch { case tpm2.IsTPMError(err, tpm2.ErrorNVDefined, tpm2.CommandNVDefineSpace): - return nil, nil, nil, TPMResourceExistsError{params.pcrPolicyCounterHandle} + return nil, nil, nil, TPMResourceExistsError{params.PcrPolicyCounterHandle} case isAuthFailError(err, tpm2.CommandNVDefineSpace, 1): return nil, nil, nil, AuthFailError{tpm2.HandleOwner} case err != nil: @@ -144,9 +144,9 @@ func makeSealedKeyData(tpm *tpm2.TPMContext, params *makeSealedKeyDataParams, se // Create the initial policy data. nameAlg := tpm2.HashAlgorithmSHA256 - requireAuthValue := params.authMode != secboot.AuthModeNone + requireAuthValue := params.AuthMode != secboot.AuthModeNone - policyData, authPolicyDigest, err := newKeyDataPolicy(nameAlg, authPublicKey, params.role, pcrPolicyCounterPub, requireAuthValue) + policyData, authPolicyDigest, err := newKeyDataPolicy(nameAlg, authPublicKey, params.Role, pcrPolicyCounterPub, requireAuthValue) if err != nil { return nil, nil, nil, xerrors.Errorf("cannot create initial policy data: %w", err) } @@ -171,7 +171,7 @@ func makeSealedKeyData(tpm *tpm2.TPMContext, params *makeSealedKeyDataParams, se skd := &SealedKeyData{sealedKeyDataBase: sealedKeyDataBase{data: data}} // Set the initial PCR policy. - pcrProfile := params.pcrProfile + pcrProfile := params.PcrProfile if pcrProfile == nil { pcrProfile = NewPCRProtectionProfile() } @@ -189,7 +189,7 @@ func makeSealedKeyData(tpm *tpm2.TPMContext, params *makeSealedKeyDataParams, se aad, err := mu.MarshalToBytes(&additionalData_v3{ BaseVersion: uint32(secboot.KeyDataVersion), KDFAlg: tpm2.HashAlgorithmSHA256, - AuthMode: params.authMode, + AuthMode: params.AuthMode, }) if err != nil { return nil, nil, nil, xerrors.Errorf("cannot create AAD: %w", err) @@ -206,7 +206,7 @@ func makeSealedKeyData(tpm *tpm2.TPMContext, params *makeSealedKeyDataParams, se ciphertext := aead.Seal(nil, symKey[32:], payload, aad) // Construct the secboot.KeyData object - kd, err := constructor.NewKeyData(skd, params.role, ciphertext, kdfAlg) + kd, err := constructor.NewKeyData(skd, params.Role, ciphertext, kdfAlg) if err != nil { return nil, nil, nil, xerrors.Errorf("cannot create key data object: %w", err) } @@ -240,11 +240,11 @@ func NewExternalTPMProtectedKey(tpmKey *tpm2.Public, params *ProtectKeyParams) ( sealer := &importableObjectKeySealer{tpmKey: tpmKey} return makeSealedKeyData(nil, &makeSealedKeyDataParams{ - primaryKey: params.PrimaryKey, - pcrPolicyCounterHandle: params.PCRPolicyCounterHandle, - authMode: secboot.AuthModeNone, - role: params.Role, - pcrProfile: params.PCRProfile, + PrimaryKey: params.PrimaryKey, + PcrPolicyCounterHandle: params.PCRPolicyCounterHandle, + AuthMode: secboot.AuthModeNone, + Role: params.Role, + PcrProfile: params.PCRProfile, }, sealer, makeKeyDataNoAuth, nil) } @@ -278,11 +278,11 @@ func NewTPMProtectedKey(tpm *Connection, params *ProtectKeyParams) (protectedKey sealer := &sealedObjectKeySealer{tpm} return makeSealedKeyData(tpm.TPMContext, &makeSealedKeyDataParams{ - pcrProfile: params.PCRProfile, - role: params.Role, - pcrPolicyCounterHandle: params.PCRPolicyCounterHandle, - primaryKey: params.PrimaryKey, - authMode: secboot.AuthModeNone, + PcrProfile: params.PCRProfile, + Role: params.Role, + PcrPolicyCounterHandle: params.PCRPolicyCounterHandle, + PrimaryKey: params.PrimaryKey, + AuthMode: secboot.AuthModeNone, }, sealer, makeKeyDataNoAuth, tpm.HmacSession()) } @@ -295,10 +295,10 @@ func NewTPMPassphraseProtectedKey(tpm *Connection, params *PassphraseProtectKeyP sealer := &sealedObjectKeySealer{tpm} return makeSealedKeyData(tpm.TPMContext, &makeSealedKeyDataParams{ - primaryKey: params.PrimaryKey, - pcrPolicyCounterHandle: params.PCRPolicyCounterHandle, - authMode: secboot.AuthModePassphrase, - role: params.Role, - pcrProfile: params.PCRProfile, + PrimaryKey: params.PrimaryKey, + PcrPolicyCounterHandle: params.PCRPolicyCounterHandle, + AuthMode: secboot.AuthModePassphrase, + Role: params.Role, + PcrProfile: params.PCRProfile, }, sealer, makeKeyDataWithPassphraseConstructor(params.KDFOptions, passphrase, kdf), tpm.HmacSession()) } diff --git a/tpm2/seal_test.go b/tpm2/seal_test.go index 8db8955a..35a88290 100644 --- a/tpm2/seal_test.go +++ b/tpm2/seal_test.go @@ -65,30 +65,20 @@ func (s *sealSuite) SetUpTest(c *C) { var _ = Suite(&sealSuite{}) func (s *sealSuite) testProtectKeyWithTPM(c *C, params *ProtectKeyParams) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + k, primaryKey, unlockKey, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) - for _, model := range params.AuthorizedSnapModels { - ok, err := k.IsSnapModelAuthorized(authKey, model) - c.Check(err, IsNil) - c.Check(ok, testutil.IsTrue) - } - skd, err := NewSealedKeyData(k) c.Assert(err, IsNil) - c.Check(skd.Validate(s.TPM().TPMContext, authKey, s.TPM().HmacSession()), IsNil) + c.Check(skd.Validate(s.TPM().TPMContext, primaryKey, s.TPM().HmacSession()), IsNil) c.Check(skd.Version(), Equals, uint32(3)) c.Check(skd.PCRPolicyCounterHandle(), Equals, params.PCRPolicyCounterHandle) - policyAuthPublicKey, err := NewPolicyAuthPublicKey(authKey) + policyAuthPublicKey, err := NewPolicyAuthPublicKey(primaryKey) c.Assert(err, IsNil) var pcrPolicyCounterPub *tpm2.NVPublic - var pcrPolicySequence uint64 if params.PCRPolicyCounterHandle != tpm2.HandleNull { index, err := s.TPM().CreateResourceContextFromTPM(params.PCRPolicyCounterHandle) c.Assert(err, IsNil) @@ -96,25 +86,23 @@ func (s *sealSuite) testProtectKeyWithTPM(c *C, params *ProtectKeyParams) { pcrPolicyCounterPub, _, err = s.TPM().NVReadPublic(index) c.Check(err, IsNil) - pcrPolicySequence, err = s.TPM().NVReadCounter(index, index, nil) - c.Check(err, IsNil) } - expectedPolicyData, expectedPolicyDigest, err := NewKeyDataPolicy(tpm2.HashAlgorithmSHA256, policyAuthPublicKey, pcrPolicyCounterPub, pcrPolicySequence) + expectedPolicyData, expectedPolicyDigest, err := NewKeyDataPolicy(tpm2.HashAlgorithmSHA256, policyAuthPublicKey, "", pcrPolicyCounterPub, false) c.Assert(err, IsNil) c.Check(skd.Data().Public().NameAlg, Equals, tpm2.HashAlgorithmSHA256) c.Check(skd.Data().Public().AuthPolicy, DeepEquals, expectedPolicyDigest) c.Check(skd.Data().Policy().(*KeyDataPolicy_v3).StaticData, tpm2_testutil.TPMValueDeepEquals, expectedPolicyData.(*KeyDataPolicy_v3).StaticData) - if params.AuthKey != nil { - c.Check(authKey, DeepEquals, params.AuthKey) + if params.PrimaryKey != nil { + c.Check(primaryKey, DeepEquals, params.PrimaryKey) } - keyUnsealed, authKeyUnsealed, err := k.RecoverKeys() + unlockKeyUnsealed, primaryKeyUnsealed, err := k.RecoverKeys() c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + c.Check(unlockKeyUnsealed, DeepEquals, unlockKey) + c.Check(primaryKeyUnsealed, DeepEquals, primaryKey) if params.PCRProfile != nil { // Verify that the key is sealed with the supplied PCR profile by changing @@ -135,28 +123,14 @@ func (s *sealSuite) TestProtectKeyWithTPM(c *C) { s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) } func (s *sealSuite) TestProtectKeyWithTPMDifferentPCRPolicyCounterHandle(c *C) { s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) } func (s *sealSuite) TestProtectKeyWithTPMWithNewConnection(c *C) { @@ -167,14 +141,7 @@ func (s *sealSuite) TestProtectKeyWithTPMWithNewConnection(c *C) { s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) s.validateSRK(c) } @@ -190,14 +157,7 @@ func (s *sealSuite) TestProtectKeyWithTPMMissingSRK(c *C) { s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) s.validateSRK(c) } @@ -238,14 +198,7 @@ func (s *sealSuite) TestProtectKeyWithTPMMissingCustomSRK(c *C) { s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) s.validatePrimaryKeyAgainstTemplate(c, tpm2.HandleOwner, tcg.SRKHandle, template) } @@ -289,14 +242,7 @@ func (s *sealSuite) TestProtectKeyWithTPMMissingSRKWithInvalidCustomTemplate(c * s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) s.validateSRK(c) } @@ -310,248 +256,17 @@ func (s *sealSuite) TestProtectKeyWithTPMNoPCRPolicyCounterHandle(c *C) { s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: tpm2.HandleNull, - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) } -func (s *sealSuite) TestProtectKeyWithTPMWithProvidedAuthKey(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) +func (s *sealSuite) TestProtectKeyWithTPMWithProvidedPrimaryKey(c *C) { + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) s.testProtectKeyWithTPM(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}, - AuthKey: authKey}) -} - -type testProtectKeysWithTPMData struct { - n int - params *ProtectKeyParams -} - -func (s *sealSuite) testProtectKeysWithTPM(c *C, data *testProtectKeysWithTPMData) { - var keys []secboot.DiskUnlockKey - for i := 0; i < data.n; i++ { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - - keys = append(keys, key) - } - - protectedKeys, authKey, err := ProtectKeysWithTPM(s.TPM(), keys, data.params) - c.Check(err, IsNil) - c.Check(protectedKeys, HasLen, data.n) - - policyAuthPublicKey, err := NewPolicyAuthPublicKey(authKey) - c.Assert(err, IsNil) - - var pcrPolicyCounterPub *tpm2.NVPublic - var pcrPolicySequence uint64 - if data.params.PCRPolicyCounterHandle != tpm2.HandleNull { - index, err := s.TPM().CreateResourceContextFromTPM(data.params.PCRPolicyCounterHandle) - c.Assert(err, IsNil) - - pcrPolicyCounterPub, _, err = s.TPM().NVReadPublic(index) - c.Check(err, IsNil) - - pcrPolicySequence, err = s.TPM().NVReadCounter(index, index, nil) - c.Check(err, IsNil) - } - - expectedPolicyData, expectedPolicyDigest, err := NewKeyDataPolicy(tpm2.HashAlgorithmSHA256, policyAuthPublicKey, pcrPolicyCounterPub, pcrPolicySequence) - c.Assert(err, IsNil) - - for i, k := range protectedKeys { - for _, model := range data.params.AuthorizedSnapModels { - ok, err := k.IsSnapModelAuthorized(authKey, model) - c.Check(err, IsNil) - c.Check(ok, testutil.IsTrue) - } - - skd, err := NewSealedKeyData(k) - c.Assert(err, IsNil) - c.Check(skd.Validate(s.TPM().TPMContext, authKey, s.TPM().HmacSession()), IsNil) - - c.Check(skd.Version(), Equals, uint32(3)) - c.Check(skd.PCRPolicyCounterHandle(), Equals, data.params.PCRPolicyCounterHandle) - - c.Check(skd.Data().Public().NameAlg, Equals, tpm2.HashAlgorithmSHA256) - c.Check(skd.Data().Public().AuthPolicy, DeepEquals, expectedPolicyDigest) - c.Check(skd.Data().Policy().(*KeyDataPolicy_v3).StaticData, tpm2_testutil.TPMValueDeepEquals, expectedPolicyData.(*KeyDataPolicy_v3).StaticData) - - keyUnsealed, authKeyUnsealed, err := k.RecoverKeys() - c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, keys[i]) - c.Check(authKeyUnsealed, DeepEquals, authKey) - } - - if data.params.AuthKey != nil { - c.Check(authKey, DeepEquals, data.params.AuthKey) - } - - if data.params.PCRProfile != nil { - // Verify that the keys are sealed with the supplied PCR profile by changing - // the PCR values. - _, err := s.TPM().PCREvent(s.TPM().PCRHandleContext(23), []byte("foo"), nil) - c.Check(err, IsNil) - - for _, k := range protectedKeys { - _, _, err = k.RecoverKeys() - c.Check(err, ErrorMatches, "invalid key data: cannot complete authorization policy assertions: cannot execute PCR assertions: "+ - "cannot execute PolicyOR assertions: current session digest not found in policy data") - } - } -} - -func (s *sealSuite) TestProtectKeysWithTPMSingle(c *C) { - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 1, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}}) -} - -func (s *sealSuite) TestProtectKeysWithTPM2Keys(c *C) { - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}}) -} - -func (s *sealSuite) TestProtectKeysWithTPMDifferentPCRPolicyCounterHandle(c *C) { - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181fff0), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}}) -} - -func (s *sealSuite) TestProtectKeysWithTPMWithNewConnection(c *C) { - // ProtectKeysWithTPM behaves slightly different if called immediately - // after EnsureProvisioned with the same Connection - s.ReinitTPMConnectionFromExisting(c) - - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}}) -} - -func (s *sealSuite) TestProtectKeysWithTPMMissingSRK(c *C) { - // Ensure that calling ProtectKeysWithTPM recreates the SRK with the standard - // template - srk, err := s.TPM().CreateResourceContextFromTPM(tcg.SRKHandle) - c.Assert(err, IsNil) - s.EvictControl(c, tpm2.HandleOwner, srk, srk.Handle()) - - s.ReinitTPMConnectionFromExisting(c) - - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}}) - - s.validateSRK(c) -} - -func (s *sealSuite) TestProtectKeyWithTPMMultipeNilPCRProfileAndNoAuthorizedSnapModels(c *C) { - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000)}}) -} - -func (s *sealSuite) TestProtectKeysWithTPMNoPCRPolicyCounterHandle(c *C) { - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: tpm2.HandleNull, - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}}) -} - -func (s *sealSuite) TestProtectKeysWithTPMWithProvidedAuthKey(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - - s.testProtectKeysWithTPM(c, &testProtectKeysWithTPMData{ - n: 2, - params: &ProtectKeyParams{ - PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}, - AuthKey: authKey}}) + PrimaryKey: primaryKey}) } func (s *sealSuite) testProtectKeyWithTPMErrorHandling(c *C, params *ProtectKeyParams) error { @@ -568,7 +283,7 @@ func (s *sealSuite) testProtectKeyWithTPMErrorHandling(c *C, params *ProtectKeyP key := make(secboot.DiskUnlockKey, 32) rand.Read(key) - _, _, sealErr := ProtectKeyWithTPM(s.TPM(), key, params) + _, _, _, sealErr := NewTPMProtectedKey(s.TPM(), params) var counter tpm2.ResourceContext if params != nil && params.PCRPolicyCounterHandle != tpm2.HandleNull { @@ -580,12 +295,13 @@ func (s *sealSuite) testProtectKeyWithTPMErrorHandling(c *C, params *ProtectKeyP c.Check(err, IsNil) } - switch { - case origCounter == nil: + if params.PCRPolicyCounterHandle == tpm2.HandleNull { c.Check(counter, IsNil) - case origCounter != nil: + } else { c.Assert(counter, NotNil) - c.Check(counter.Name(), DeepEquals, origCounter.Name()) + if origCounter != nil { + c.Check(counter.Name(), DeepEquals, origCounter.Name()) + } } return sealErr @@ -607,20 +323,6 @@ func (s *sealSuite) TestProtectKeyWithTPMErrorHandlingOwnerAuthFail(c *C) { c.Check(err.(AuthFailError).Handle, Equals, tpm2.HandleOwner) } -func (s *sealSuite) TestProtectKeyWithTPMErrorHandlingPCRPolicyCounterExists(c *C) { - public := tpm2.NVPublic{ - Index: s.NextAvailableHandle(c, 0x0181ffff), - NameAlg: tpm2.HashAlgorithmSHA256, - Attrs: tpm2.NVTypeOrdinary.WithAttrs(tpm2.AttrNVAuthWrite | tpm2.AttrNVAuthRead), - Size: 0} - s.NVDefineSpace(c, tpm2.HandleOwner, nil, &public) - - err := s.testProtectKeyWithTPMErrorHandling(c, &ProtectKeyParams{ - PCRPolicyCounterHandle: public.Index}) - c.Assert(err, testutil.ConvertibleTo, TPMResourceExistsError{}) - c.Check(err.(TPMResourceExistsError).Handle, Equals, public.Index) -} - func (s *sealSuite) TestProtectKeyWithTPMErrorHandlingInvalidPCRProfile(c *C) { err := s.testProtectKeyWithTPMErrorHandling(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7}). @@ -650,40 +352,34 @@ func (s *sealSuite) testProtectKeyWithExternalStorageKey(c *C, params *ProtectKe key := make(secboot.DiskUnlockKey, 32) rand.Read(key) - k, authKey, err := ProtectKeyWithExternalStorageKey(srkPub, key, params) + k, primaryKey, unlockKey, err := NewExternalTPMProtectedKey(srkPub, params) c.Assert(err, IsNil) - for _, model := range params.AuthorizedSnapModels { - ok, err := k.IsSnapModelAuthorized(authKey, model) - c.Check(err, IsNil) - c.Check(ok, testutil.IsTrue) - } - skd, err := NewSealedKeyData(k) c.Assert(err, IsNil) - c.Check(skd.Validate(s.TPM().TPMContext, authKey, s.TPM().HmacSession()), IsNil) + c.Check(skd.Validate(s.TPM().TPMContext, primaryKey, s.TPM().HmacSession()), IsNil) c.Check(skd.Version(), Equals, uint32(3)) c.Check(skd.PCRPolicyCounterHandle(), Equals, tpm2.HandleNull) - policyAuthPublicKey, err := NewPolicyAuthPublicKey(authKey) + policyAuthPublicKey, err := NewPolicyAuthPublicKey(primaryKey) c.Assert(err, IsNil) - expectedPolicyData, expectedPolicyDigest, err := NewKeyDataPolicy(tpm2.HashAlgorithmSHA256, policyAuthPublicKey, nil, 0) + expectedPolicyData, expectedPolicyDigest, err := NewKeyDataPolicy(tpm2.HashAlgorithmSHA256, policyAuthPublicKey, "", nil, false) c.Assert(err, IsNil) c.Check(skd.Data().Public().NameAlg, Equals, tpm2.HashAlgorithmSHA256) c.Check(skd.Data().Public().AuthPolicy, DeepEquals, expectedPolicyDigest) c.Check(skd.Data().Policy().(*KeyDataPolicy_v3).StaticData, tpm2_testutil.TPMValueDeepEquals, expectedPolicyData.(*KeyDataPolicy_v3).StaticData) - if params.AuthKey != nil { - c.Check(authKey, DeepEquals, params.AuthKey) + if params.PrimaryKey != nil { + c.Check(primaryKey, DeepEquals, params.PrimaryKey) } - keyUnsealed, authKeyUnsealed, err := k.RecoverKeys() + unlockKeyUnsealed, primaryKeyUnsealed, err := k.RecoverKeys() c.Check(err, IsNil) - c.Check(keyUnsealed, DeepEquals, key) - c.Check(authKeyUnsealed, DeepEquals, authKey) + c.Check(unlockKeyUnsealed, DeepEquals, unlockKey) + c.Check(primaryKeyUnsealed, DeepEquals, primaryKey) if params.PCRProfile != nil { // Verify that the key is sealed with the supplied PCR profile by changing @@ -700,14 +396,7 @@ func (s *sealSuite) TestProtectKeyWithExternalStorageKey(c *C) { s.testProtectKeyWithExternalStorageKey(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewResolvedPCRProfileFromCurrentValues(c, s.TPM().TPMContext, tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: tpm2.HandleNull, - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}}) + }) } func (s *sealSuite) TestProtectKeyWithExternalStorageKeyNilPCRProfileAndNoAuthorizedSnapModels(c *C) { @@ -715,22 +404,14 @@ func (s *sealSuite) TestProtectKeyWithExternalStorageKeyNilPCRProfileAndNoAuthor PCRPolicyCounterHandle: tpm2.HandleNull}) } -func (s *sealSuite) TestProtectKeyWithExternalStorageKeyWithProvidedAuthKey(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) +func (s *sealSuite) TestProtectKeyWithExternalStorageKeyWithProvidedPrimaryKey(c *C) { + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) s.testProtectKeyWithExternalStorageKey(c, &ProtectKeyParams{ PCRProfile: tpm2test.NewResolvedPCRProfileFromCurrentValues(c, s.TPM().TPMContext, tpm2.HashAlgorithmSHA256, []int{7, 23}), PCRPolicyCounterHandle: tpm2.HandleNull, - AuthorizedSnapModels: []secboot.SnapModel{ - testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ - "authority-id": "fake-brand", - "series": "16", - "brand-id": "fake-brand", - "model": "fake-model", - "grade": "secured", - }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")}, - AuthKey: authKey}) + PrimaryKey: primaryKey}) } func (s *sealSuite) testProtectKeyWithExternalStorageKeyErrorHandling(c *C, params *ProtectKeyParams) error { @@ -743,7 +424,7 @@ func (s *sealSuite) testProtectKeyWithExternalStorageKeyErrorHandling(c *C, para key := make(secboot.DiskUnlockKey, 32) rand.Read(key) - _, _, sealErr := ProtectKeyWithExternalStorageKey(srkPub, key, params) + _, _, _, sealErr := NewExternalTPMProtectedKey(srkPub, params) return sealErr } @@ -766,13 +447,6 @@ func (s *sealSuite) TestProtectKeyWithExternalStorageKeyErrorHandlingInvalidPCRP c.Check(err, ErrorMatches, "cannot set initial PCR policy: PCR protection profile contains digests for unsupported PCRs") } -func (s *sealSuite) TestProtectKeyWithExternalStorageKeyErrorHandlingWithPCRPolicyCounter(c *C) { - err := s.testProtectKeyWithExternalStorageKeyErrorHandling(c, &ProtectKeyParams{ - PCRProfile: tpm2test.NewResolvedPCRProfileFromCurrentValues(c, s.TPM().TPMContext, tpm2.HashAlgorithmSHA256, []int{7}), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000)}) - c.Check(err, ErrorMatches, "PCR policy counter handle must be tpm2.HandleNull when creating an importable sealed key") -} - type mockKeySealer struct { called bool } @@ -812,264 +486,39 @@ func (s *sealSuiteNoTPM) SetUpTest(c *C) { s.lastAuthKey = nil s.lastAuthKeyPublic = nil - s.AddCleanup(MockNewPolicyAuthPublicKey(func(authKey secboot.PrimaryKey) (*tpm2.Public, error) { - s.lastAuthKey = authKey + s.AddCleanup(MockNewPolicyAuthPublicKey(func(primaryKey secboot.PrimaryKey) (*tpm2.Public, error) { + s.lastAuthKey = primaryKey - pub, err := NewPolicyAuthPublicKey(authKey) + pub, err := NewPolicyAuthPublicKey(primaryKey) s.lastAuthKeyPublic = pub return pub, err })) -} - -var _ = Suite(&sealSuiteNoTPM{}) - -type testMakeKeyDataWithPolicyData struct { - policy *KeyDataPolicyParams -} - -func (s *sealSuiteNoTPM) testMakeKeyDataWithPolicy(c *C, data *testMakeKeyDataWithPolicyData) { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - - var sealer mockKeySealer - - kd, err := MakeKeyDataWithPolicy(key, authKey, data.policy, &sealer) - c.Check(err, IsNil) - c.Assert(kd, NotNil) - - c.Assert(s.lastKeyParams, NotNil) - c.Check(s.lastKeyParams.PlatformName, Equals, "tpm2") - c.Check(s.lastKeyParams.PrimaryKey, DeepEquals, authKey) - c.Check(s.lastKeyParams.SnapModelAuthHash, Equals, crypto.SHA256) - - skd, err := NewSealedKeyData(kd) - c.Assert(err, IsNil) - - c.Check(skd.Data().Policy(), tpm2_testutil.TPMValueDeepEquals, data.policy.PolicyData) - c.Check(skd.Data().Public().NameAlg, Equals, data.policy.Alg) - c.Check(skd.Data().Public().AuthPolicy, DeepEquals, data.policy.AuthPolicy) - - payload := make(secboot.KeyPayload, len(s.lastKeyParams.EncryptedPayload)) - - c.Assert(skd.Data().Private(), HasLen, 48) - b, err := aes.NewCipher(skd.Data().Private()[:32]) - c.Assert(err, IsNil) - stream := cipher.NewCFBDecrypter(b, skd.Data().Private()[32:]) - stream.XORKeyStream(payload, s.lastKeyParams.EncryptedPayload) - - recoveredKey, recoveredAuthKey, err := payload.Unmarshal() - c.Check(err, IsNil) - c.Check(recoveredKey, DeepEquals, key) - c.Check(recoveredAuthKey, DeepEquals, authKey) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataWithPolicy(c *C) { - policyData := &KeyDataPolicy_v3{ - StaticData: &StaticPolicyData_v3{ - AuthPublicKey: templates.NewECCKey(tpm2.HashAlgorithmSHA256, templates.KeyUsageSign, nil, tpm2.ECCCurveNIST_P256), - PCRPolicyCounterHandle: tpm2.HandleNull, - }, - PCRData: &PcrPolicyData_v3{ - AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgECDSA}, - }, - } - - s.testMakeKeyDataWithPolicy(c, &testMakeKeyDataWithPolicyData{ - policy: &KeyDataPolicyParams{ - Alg: tpm2.HashAlgorithmSHA256, - PolicyData: policyData, - AuthPolicy: []byte{1, 2, 3, 4}}}) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataWithPolicyDifferentNameAlg(c *C) { - policyData := &KeyDataPolicy_v3{ - StaticData: &StaticPolicyData_v3{ - AuthPublicKey: templates.NewECCKey(tpm2.HashAlgorithmSHA256, templates.KeyUsageSign, nil, tpm2.ECCCurveNIST_P256), - PCRPolicyCounterHandle: tpm2.HandleNull, - }, - PCRData: &PcrPolicyData_v3{ - AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgECDSA}, - }, - } - - s.testMakeKeyDataWithPolicy(c, &testMakeKeyDataWithPolicyData{ - policy: &KeyDataPolicyParams{ - Alg: tpm2.HashAlgorithmSHA1, - PolicyData: policyData, - AuthPolicy: []byte{1, 2, 3, 4}}}) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataWithPolicyDifferentPolicyDigest(c *C) { - policyData := &KeyDataPolicy_v3{ - StaticData: &StaticPolicyData_v3{ - AuthPublicKey: templates.NewECCKey(tpm2.HashAlgorithmSHA256, templates.KeyUsageSign, nil, tpm2.ECCCurveNIST_P256), - PCRPolicyCounterHandle: tpm2.HandleNull, - }, - PCRData: &PcrPolicyData_v3{ - AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgECDSA}, - }, - } - - s.testMakeKeyDataWithPolicy(c, &testMakeKeyDataWithPolicyData{ - policy: &KeyDataPolicyParams{ - Alg: tpm2.HashAlgorithmSHA256, - PolicyData: policyData, - AuthPolicy: []byte{5, 6, 7, 8, 9}}}) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataWithPolicyDifferentPolicyVersion(c *C) { - policyData := &KeyDataPolicy_v1{ - StaticData: &StaticPolicyData_v1{ - AuthPublicKey: templates.NewECCKey(tpm2.HashAlgorithmSHA256, templates.KeyUsageSign, nil, tpm2.ECCCurveNIST_P256), - PCRPolicyCounterHandle: tpm2.HandleNull, - }, - PCRData: &PcrPolicyData_v1{ - AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgECDSA}, - }, - } - - s.testMakeKeyDataWithPolicy(c, &testMakeKeyDataWithPolicyData{ - policy: &KeyDataPolicyParams{ - Alg: tpm2.HashAlgorithmSHA256, - PolicyData: policyData, - AuthPolicy: []byte{1, 2, 3, 4}}}) -} - -type testMakeKeyDataPolicyData struct { - pcrPolicyCounterHandle tpm2.Handle - authKey secboot.PrimaryKey - initialPcrPolicyCounterValue uint64 -} - -func (s *sealSuiteNoTPM) testMakeKeyDataPolicy(c *C, data *testMakeKeyDataPolicyData) { - var mockTpm *tpm2.TPMContext - var mockSession tpm2.SessionContext - if data.pcrPolicyCounterHandle != tpm2.HandleNull { - mockTpm = new(tpm2.TPMContext) - mockSession = new(mockSessionContext) - } - - var mockPcrPolicyCounterPub *tpm2.NVPublic - restore := MockCreatePcrPolicyCounter(func(tpm *tpm2.TPMContext, handle tpm2.Handle, pub *tpm2.Public, session tpm2.SessionContext) (*tpm2.NVPublic, uint64, error) { - c.Assert(mockTpm, NotNil) - - c.Check(tpm, Equals, mockTpm) - c.Check(handle, Equals, data.pcrPolicyCounterHandle) - c.Check(pub, Equals, s.lastAuthKeyPublic) - c.Check(session, Equals, mockSession) - - mockPcrPolicyCounterPub = &tpm2.NVPublic{ - Index: handle, - NameAlg: tpm2.HashAlgorithmSHA256, - Attrs: tpm2.NVTypeCounter.WithAttrs(tpm2.AttrNVPolicyWrite | tpm2.AttrNVAuthRead | tpm2.AttrNVNoDA), - AuthPolicy: make([]byte, 32), - Size: 8} - - return mockPcrPolicyCounterPub, data.initialPcrPolicyCounterValue, nil - }) - defer restore() - - var mockPolicyData *KeyDataPolicy_v3 - var mockPolicyDigest tpm2.Digest - restore = MockNewKeyDataPolicy(func(alg tpm2.HashAlgorithmId, key *tpm2.Public, pcrPolicyCounterPub *tpm2.NVPublic, pcrPolicySequence uint64) (KeyDataPolicy, tpm2.Digest, error) { - c.Check(alg, Equals, tpm2.HashAlgorithmSHA256) - c.Check(key, Equals, s.lastAuthKeyPublic) - c.Check(pcrPolicyCounterPub, Equals, mockPcrPolicyCounterPub) - c.Check(pcrPolicySequence, Equals, data.initialPcrPolicyCounterValue) - - index := tpm2.HandleNull - if pcrPolicyCounterPub != nil { - index = pcrPolicyCounterPub.Index - } - - mockPolicyData = &KeyDataPolicy_v3{ - StaticData: &StaticPolicyData_v3{ - AuthPublicKey: key, - PCRPolicyCounterHandle: index}, - PCRData: &PcrPolicyData_v3{ - PolicySequence: pcrPolicySequence, - AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgNull}}} - - mockPolicyDigest = make([]byte, alg.Size()) - rand.Read(mockPolicyDigest) - - return mockPolicyData, mockPolicyDigest, nil - }) - defer restore() - - policy, pcrPolicyCounter, authKeyOut, err := MakeKeyDataPolicy(mockTpm, data.pcrPolicyCounterHandle, data.authKey, mockSession) - c.Assert(err, IsNil) - - c.Assert(s.lastAuthKey, NotNil) - c.Assert(mockPolicyData, NotNil) - - c.Assert(policy, NotNil) - c.Check(policy.Alg, Equals, tpm2.HashAlgorithmSHA256) - c.Assert(policy.PolicyData, testutil.ConvertibleTo, new(KeyDataPolicy_v3)) - c.Check(policy.PolicyData.(*KeyDataPolicy_v3), Equals, mockPolicyData) - c.Check(policy.AuthPolicy, DeepEquals, mockPolicyDigest) - - if data.pcrPolicyCounterHandle == tpm2.HandleNull { - c.Check(pcrPolicyCounter, IsNil) - } else { - c.Check(pcrPolicyCounter, NotNil) - c.Check(pcrPolicyCounter.Pub(), Equals, mockPcrPolicyCounterPub) - c.Check(pcrPolicyCounter.TPM(), Equals, mockTpm) - c.Check(pcrPolicyCounter.Session(), Equals, mockSession) - } - - c.Check(authKeyOut, DeepEquals, s.lastAuthKey) - c.Check(policy.PolicyData.ValidateAuthKey(authKeyOut), IsNil) - if data.authKey != nil { - c.Check(authKeyOut, DeepEquals, data.authKey) - } } -func (s *sealSuiteNoTPM) TestMakeKeyDataPolicy(c *C) { - s.testMakeKeyDataPolicy(c, &testMakeKeyDataPolicyData{ - pcrPolicyCounterHandle: tpm2.HandleNull}) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataPolicyWithPolicyCounter(c *C) { - s.testMakeKeyDataPolicy(c, &testMakeKeyDataPolicyData{ - pcrPolicyCounterHandle: 0x01800001, - initialPcrPolicyCounterValue: 20}) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataPolicyWithPolicyCounterDifferentInitialValue(c *C) { - s.testMakeKeyDataPolicy(c, &testMakeKeyDataPolicyData{ - pcrPolicyCounterHandle: 0x01800001, - initialPcrPolicyCounterValue: 1000}) -} - -func (s *sealSuiteNoTPM) TestMakeKeyDataPolicyWithProvidedAuthKey(c *C) { - s.testMakeKeyDataPolicy(c, &testMakeKeyDataPolicyData{ - authKey: testutil.DecodeHexString(c, "fb8978601d0c2dd4129e3b9c1bb3f3116f4c5dd217c29b1017ab7cd31a882d3c")}) -} +var _ = Suite(&sealSuiteNoTPM{}) -type testMakeKeyDataData struct { - authKey secboot.PrimaryKey - params *KeyDataParams - initialPcrPolicyCounterValue uint64 +type testMakeSealedKeyDataData struct { + PCRProfile *PCRProtectionProfile + Role string + PCRPolicyCounterHandle tpm2.Handle + PrimaryKey secboot.PrimaryKey } -func (s *sealSuiteNoTPM) testMakeKeyData(c *C, data *testMakeKeyDataData) { +func (s *sealSuiteNoTPM) testMakeSealedKeyData(c *C, data *testMakeSealedKeyDataData) { var mockTpm *tpm2.TPMContext var mockSession tpm2.SessionContext - if data.params.PCRPolicyCounterHandle != tpm2.HandleNull { + if data.PCRPolicyCounterHandle != tpm2.HandleNull { mockTpm = new(tpm2.TPMContext) mockSession = new(mockSessionContext) } var mockPcrPolicyCounterPub *tpm2.NVPublic - restore := MockCreatePcrPolicyCounter(func(tpm *tpm2.TPMContext, handle tpm2.Handle, pub *tpm2.Public, session tpm2.SessionContext) (*tpm2.NVPublic, uint64, error) { + restore := MockEnsurePcrPolicyCounter(func(tpm *tpm2.TPMContext, handle tpm2.Handle, pub *tpm2.Public, session tpm2.SessionContext) (*tpm2.NVPublic, error) { c.Assert(mockTpm, NotNil) c.Check(tpm, Equals, mockTpm) - c.Check(handle, Equals, data.params.PCRPolicyCounterHandle) + c.Check(handle, Equals, data.PCRPolicyCounterHandle) c.Check(pub, Equals, s.lastAuthKeyPublic) c.Check(session, Equals, mockSession) @@ -1080,17 +529,17 @@ func (s *sealSuiteNoTPM) testMakeKeyData(c *C, data *testMakeKeyDataData) { AuthPolicy: make([]byte, 32), Size: 8} - return mockPcrPolicyCounterPub, data.initialPcrPolicyCounterValue, nil + return mockPcrPolicyCounterPub, nil }) defer restore() var mockPolicyData *KeyDataPolicy_v3 var mockPolicyDigest tpm2.Digest - restore = MockNewKeyDataPolicy(func(alg tpm2.HashAlgorithmId, key *tpm2.Public, pcrPolicyCounterPub *tpm2.NVPublic, pcrPolicySequence uint64) (KeyDataPolicy, tpm2.Digest, error) { + restore = MockNewKeyDataPolicy(func(alg tpm2.HashAlgorithmId, key *tpm2.Public, role string, pcrPolicyCounterPub *tpm2.NVPublic, requireAuthValue bool) (KeyDataPolicy, tpm2.Digest, error) { c.Check(alg, Equals, tpm2.HashAlgorithmSHA256) c.Check(key, Equals, s.lastAuthKeyPublic) c.Check(pcrPolicyCounterPub, Equals, mockPcrPolicyCounterPub) - c.Check(pcrPolicySequence, Equals, data.initialPcrPolicyCounterValue) + c.Check(requireAuthValue, Equals, false) index := tpm2.HandleNull if pcrPolicyCounterPub != nil { @@ -1102,7 +551,6 @@ func (s *sealSuiteNoTPM) testMakeKeyData(c *C, data *testMakeKeyDataData) { AuthPublicKey: key, PCRPolicyCounterHandle: index}, PCRData: &PcrPolicyData_v3{ - PolicySequence: pcrPolicySequence, AuthorizedPolicySignature: &tpm2.Signature{SigAlg: tpm2.SigSchemeAlgNull}}} mockPolicyDigest = make([]byte, alg.Size()) @@ -1113,15 +561,16 @@ func (s *sealSuiteNoTPM) testMakeKeyData(c *C, data *testMakeKeyDataData) { defer restore() pcrPolicyInitialized := false - restore = MockSkdbUpdatePCRProtectionPolicyImpl(func(skdb *SealedKeyDataBase, tpm *tpm2.TPMContext, authKey secboot.PrimaryKey, counterPub *tpm2.NVPublic, profile *PCRProtectionProfile, session tpm2.SessionContext) error { + restore = MockSkdbUpdatePCRProtectionPolicyNoValidate(func(skdb *SealedKeyDataBase, tpm *tpm2.TPMContext, primaryKey secboot.PrimaryKey, counterPub *tpm2.NVPublic, profile *PCRProtectionProfile, incrementPolicyVersion bool, session tpm2.SessionContext) error { c.Check(tpm, Equals, mockTpm) - c.Check(authKey, DeepEquals, s.lastAuthKey) + c.Check(primaryKey, DeepEquals, s.lastAuthKey) c.Check(counterPub, Equals, mockPcrPolicyCounterPub) c.Check(profile, NotNil) - if data.params.PCRProfile != nil { - c.Check(profile, Equals, data.params.PCRProfile) + if data.PCRProfile != nil { + c.Check(profile, Equals, data.PCRProfile) } c.Check(session, Equals, mockSession) + c.Check(incrementPolicyVersion, testutil.IsFalse) pcrPolicyInitialized = true return nil }) @@ -1129,10 +578,19 @@ func (s *sealSuiteNoTPM) testMakeKeyData(c *C, data *testMakeKeyDataData) { var sealer mockKeySealer - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) - kd, authKeyOut, pcrPolicyCounter, err := MakeKeyData(mockTpm, key, data.authKey, data.params, &sealer, mockSession) + params := &SealedKeyDataParams{ + PcrProfile: data.PCRProfile, + Role: data.Role, + PcrPolicyCounterHandle: data.PCRPolicyCounterHandle, + PrimaryKey: primaryKey, + } + + constructor := MakeKeyDataNoAuth + + kd, pk, _, err := MakeSealedKeyData(mockTpm, params, &sealer, constructor, mockSession) c.Assert(err, IsNil) c.Assert(s.lastAuthKey, NotNil) @@ -1141,70 +599,57 @@ func (s *sealSuiteNoTPM) testMakeKeyData(c *C, data *testMakeKeyDataData) { c.Assert(s.lastKeyParams, NotNil) c.Check(s.lastKeyParams.PlatformName, Equals, "tpm2") - c.Check(s.lastKeyParams.PrimaryKey, DeepEquals, s.lastAuthKey) - c.Check(s.lastKeyParams.SnapModelAuthHash, Equals, crypto.SHA256) + c.Check(s.lastKeyParams.Role, Equals, data.Role) + c.Check(s.lastKeyParams.KDFAlg, Equals, crypto.SHA256) - skd, err := NewSealedKeyData(kd) - c.Assert(err, IsNil) + c.Check(pk, DeepEquals, primaryKey) + c.Check(kd.Role(), DeepEquals, data.Role) + + var skd *SealedKeyData + c.Check(kd.UnmarshalPlatformHandle(&skd), IsNil) c.Check(skd.Data().Policy(), tpm2_testutil.TPMValueDeepEquals, mockPolicyData) c.Check(skd.Data().Public().NameAlg, Equals, tpm2.HashAlgorithmSHA256) c.Check(skd.Data().Public().AuthPolicy, DeepEquals, mockPolicyDigest) - payload := make(secboot.KeyPayload, len(s.lastKeyParams.EncryptedPayload)) + payload := make([]byte, len(s.lastKeyParams.EncryptedPayload)) - c.Assert(skd.Data().Private(), HasLen, 48) + c.Assert(skd.Data().Private(), HasLen, 44) b, err := aes.NewCipher(skd.Data().Private()[:32]) c.Assert(err, IsNil) - stream := cipher.NewCFBDecrypter(b, skd.Data().Private()[32:]) - stream.XORKeyStream(payload, s.lastKeyParams.EncryptedPayload) - recoveredKey, recoveredAuthKey, err := payload.Unmarshal() - c.Check(err, IsNil) - c.Check(recoveredKey, DeepEquals, key) - c.Check(recoveredAuthKey, DeepEquals, s.lastAuthKey) + aad, err := mu.MarshalToBytes(&AdditionalData_v3{ + BaseVersion: uint32(kd.Version()), + KDFAlg: tpm2.HashAlgorithmSHA256, + AuthMode: kd.AuthMode(), + }) - c.Check(skd.Data().Policy().ValidateAuthKey(authKeyOut), IsNil) - c.Check(authKeyOut, DeepEquals, s.lastAuthKey) - if data.authKey != nil { - c.Check(authKeyOut, DeepEquals, data.authKey) - } + aead, err := cipher.NewGCM(b) + c.Assert(err, IsNil) - if data.params.PCRPolicyCounterHandle == tpm2.HandleNull { - c.Check(pcrPolicyCounter, IsNil) - } else { - c.Check(pcrPolicyCounter, NotNil) - c.Check(pcrPolicyCounter.Pub(), Equals, mockPcrPolicyCounterPub) - c.Check(pcrPolicyCounter.TPM(), Equals, mockTpm) - c.Check(pcrPolicyCounter.Session(), Equals, mockSession) - } -} + payload, err = aead.Open(nil, skd.Data().Private()[32:], s.lastKeyParams.EncryptedPayload, aad) + c.Assert(err, IsNil) -func (s *sealSuiteNoTPM) TestMakeKeyData(c *C) { - s.testMakeKeyData(c, &testMakeKeyDataData{ - params: &KeyDataParams{ - PCRPolicyCounterHandle: tpm2.HandleNull, - PCRProfile: NewPCRProtectionProfile()}}) -} + keys, err := UnmarshalProtectedKeys(payload) + c.Check(err, IsNil) -func (s *sealSuiteNoTPM) TestMakeKeyDataWithPolicyCounter(c *C) { - s.testMakeKeyData(c, &testMakeKeyDataData{ - params: &KeyDataParams{ - PCRPolicyCounterHandle: 0x01810000, - PCRProfile: NewPCRProtectionProfile()}, - initialPcrPolicyCounterValue: 30}) + c.Check(keys.Primary, DeepEquals, primaryKey) + + c.Check(skd.Data().Policy().ValidateAuthKey(keys.Primary), IsNil) } -func (s *sealSuiteNoTPM) TestMakeKeyDataWithPolicyCounterDifferentInitialValue(c *C) { - s.testMakeKeyData(c, &testMakeKeyDataData{ - params: &KeyDataParams{ - PCRPolicyCounterHandle: 0x01810000, - PCRProfile: NewPCRProtectionProfile()}, - initialPcrPolicyCounterValue: 500}) +func (s *sealSuiteNoTPM) TestMakeSealedKeyData(c *C) { + s.testMakeSealedKeyData(c, &testMakeSealedKeyDataData{ + PCRProfile: NewPCRProtectionProfile(), + PCRPolicyCounterHandle: 0x01800000, + Role: "", + }) } -func (s *sealSuiteNoTPM) TestMakeKeyDataNilPCRProfile(c *C) { - s.testMakeKeyData(c, &testMakeKeyDataData{ - params: &KeyDataParams{ - PCRPolicyCounterHandle: tpm2.HandleNull}}) +func (s *sealSuiteNoTPM) TestMakeSealedKeyData2(c *C) { + s.testMakeSealedKeyData(c, &testMakeSealedKeyDataData{ + PCRProfile: NewPCRProtectionProfile(), + PCRPolicyCounterHandle: 0x01800000, + Role: "test", + }) } diff --git a/tpm2/update_test.go b/tpm2/update_test.go index 33f658ab..9ad1f5d0 100644 --- a/tpm2/update_test.go +++ b/tpm2/update_test.go @@ -57,7 +57,7 @@ var _ = Suite(&updateSuite{}) type testUpdatePCRProtectionPolicyData struct { pcrPolicyCounterHandle tpm2.Handle - authKey secboot.PrimaryKey + primaryKey secboot.PrimaryKey } func (s *updateSuite) testUpdatePCRProtectionPolicy(c *C, data *testUpdatePCRProtectionPolicyData) { @@ -68,8 +68,8 @@ func (s *updateSuite) testUpdatePCRProtectionPolicy(c *C, data *testUpdatePCRPro params := &ProtectKeyParams{ PCRProfile: NewPCRProtectionProfile().AddPCRValue(tpm2.HashAlgorithmSHA256, 7, testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), PCRPolicyCounterHandle: data.pcrPolicyCounterHandle, - AuthKey: data.authKey} - k, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + PrimaryKey: data.primaryKey} + k, primaryKey, _, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) _, _, err = k.RecoverKeys() @@ -79,7 +79,7 @@ func (s *updateSuite) testUpdatePCRProtectionPolicy(c *C, data *testUpdatePCRPro skd, err := NewSealedKeyData(k) c.Assert(err, IsNil) - c.Check(skd.UpdatePCRProtectionPolicy(s.TPM(), authKey, tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23})), IsNil) + c.Check(skd.UpdatePCRProtectionPolicy(s.TPM(), primaryKey, tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), false), IsNil) _, _, err = k.RecoverKeys() c.Check(err, IsNil) @@ -102,19 +102,16 @@ func (s *updateSuite) TestUpdatePCRProtectionPolicyNoPCRPolicyCounter(c *C) { } func (s *updateSuite) TestUpdatePCRProtectionPolicyWithProvidedAuthKey(c *C) { - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) + primaryKey := make(secboot.PrimaryKey, 32) + rand.Read(primaryKey) s.testUpdatePCRProtectionPolicy(c, &testUpdatePCRProtectionPolicyData{ pcrPolicyCounterHandle: s.NextAvailableHandle(c, 0x01810000), - authKey: authKey}) + primaryKey: primaryKey}) } func (s *updateSuite) testRevokeOldPCRProtectionPolicies(c *C, params *ProtectKeyParams) error { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - - k1, authKey, err := ProtectKeyWithTPM(s.TPM(), key, params) + k1, primaryKey, _, err := NewTPMProtectedKey(s.TPM(), params) c.Assert(err, IsNil) w := newMockKeyDataWriter() @@ -125,7 +122,7 @@ func (s *updateSuite) testRevokeOldPCRProtectionPolicies(c *C, params *ProtectKe skd, err := NewSealedKeyData(k2) c.Assert(err, IsNil) - c.Check(skd.UpdatePCRProtectionPolicy(s.TPM(), authKey, params.PCRProfile), IsNil) + c.Check(skd.UpdatePCRProtectionPolicy(s.TPM(), primaryKey, params.PCRProfile, true), IsNil) _, _, err = k1.RecoverKeys() c.Check(err, IsNil) @@ -134,7 +131,7 @@ func (s *updateSuite) testRevokeOldPCRProtectionPolicies(c *C, params *ProtectKe skd, err = NewSealedKeyData(k1) c.Assert(err, IsNil) - c.Check(skd.RevokeOldPCRProtectionPolicies(s.TPM(), authKey), IsNil) + c.Check(skd.RevokeOldPCRProtectionPolicies(s.TPM(), primaryKey), IsNil) _, _, err = k1.RecoverKeys() c.Check(err, IsNil) @@ -143,7 +140,7 @@ func (s *updateSuite) testRevokeOldPCRProtectionPolicies(c *C, params *ProtectKe skd, err = NewSealedKeyData(k2) c.Assert(err, IsNil) - c.Check(skd.RevokeOldPCRProtectionPolicies(s.TPM(), authKey), IsNil) + c.Check(skd.RevokeOldPCRProtectionPolicies(s.TPM(), primaryKey), IsNil) _, _, err = k2.RecoverKeys() c.Check(err, IsNil) @@ -164,107 +161,3 @@ func (s *updateSuite) TestRevokeOldPCRProtectionPoliciesWithoutPCRPolicyCounter( PCRPolicyCounterHandle: tpm2.HandleNull}) c.Check(err, IsNil) } - -func (s *updateSuite) testUpdateKeyDataPCRProtectionPolicy(c *C, n int) { - var keys []secboot.DiskUnlockKey - for i := 0; i < n; i++ { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - keys = append(keys, key) - } - - // Protect the key with an initial PCR policy that can't be satisfied - params := &ProtectKeyParams{ - PCRProfile: NewPCRProtectionProfile().AddPCRValue(tpm2.HashAlgorithmSHA256, 7, testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - PCRPolicyCounterHandle: tpm2.HandleNull} - ks, authKey, err := ProtectKeysWithTPM(s.TPM(), keys, params) - c.Assert(err, IsNil) - - for _, k := range ks { - _, _, err = k.RecoverKeys() - c.Check(err, ErrorMatches, "invalid key data: cannot complete authorization policy assertions: cannot execute PCR assertions: "+ - "cannot execute PolicyOR assertions: current session digest not found in policy data") - } - - c.Check(UpdateKeyDataPCRProtectionPolicy(s.TPM(), authKey, tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), ks...), IsNil) - - for _, k := range ks { - _, _, err = k.RecoverKeys() - c.Check(err, IsNil) - } - - _, err = s.TPM().PCREvent(s.TPM().PCRHandleContext(23), []byte("foo"), nil) - c.Check(err, IsNil) - - for _, k := range ks { - _, _, err = k.RecoverKeys() - c.Check(err, ErrorMatches, "invalid key data: cannot complete authorization policy assertions: cannot execute PCR assertions: "+ - "cannot execute PolicyOR assertions: current session digest not found in policy data") - } -} - -func (s *updateSuite) TestUpdateKeyDataPCRProtectionPolicy1(c *C) { - s.testUpdateKeyDataPCRProtectionPolicy(c, 1) -} - -func (s *updateSuite) TestUpdateKeyDataPCRProtectionPolicy2(c *C) { - s.testUpdateKeyDataPCRProtectionPolicy(c, 2) -} - -func (s *updateSuite) TestUpdateKeyDataPCRProtectionPolicy3(c *C) { - s.testUpdateKeyDataPCRProtectionPolicy(c, 3) -} - -func (s *updateSuite) TestUpdateKeyDataPCRProtectionPolicyUnrelated1(c *C) { - var keys []secboot.DiskUnlockKey - for i := 0; i < 2; i++ { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - keys = append(keys, key) - } - - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - - var ks []*secboot.KeyData - for i := 0; i < 2; i++ { - params := &ProtectKeyParams{ - PCRProfile: NewPCRProtectionProfile().AddPCRValue(tpm2.HashAlgorithmSHA256, 7, testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - PCRPolicyCounterHandle: s.NextAvailableHandle(c, 0x0181ff00+tpm2.Handle(i)), - AuthKey: authKey} - k, _, err := ProtectKeyWithTPM(s.TPM(), keys[i], params) - c.Assert(err, IsNil) - ks = append(ks, k) - } - - err := UpdateKeyDataPCRProtectionPolicy(s.TPM(), authKey, tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), ks...) - c.Check(err, ErrorMatches, "invalid key data: key data at index 1 is not related to the primary key data") -} - -func (s *updateSuite) TestUpdateKeyDataPCRProtectionPolicyUnrelated2(c *C) { - var keys []secboot.DiskUnlockKey - var authKeys []secboot.PrimaryKey - for i := 0; i < 2; i++ { - key := make(secboot.DiskUnlockKey, 32) - rand.Read(key) - keys = append(keys, key) - - authKey := make(secboot.PrimaryKey, 32) - rand.Read(authKey) - authKeys = append(authKeys, authKey) - } - - var ks []*secboot.KeyData - for i := 0; i < 2; i++ { - params := &ProtectKeyParams{ - PCRProfile: NewPCRProtectionProfile().AddPCRValue(tpm2.HashAlgorithmSHA256, 7, testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), - PCRPolicyCounterHandle: tpm2.HandleNull, - AuthKey: authKeys[i]} - k, _, err := ProtectKeyWithTPM(s.TPM(), keys[i], params) - c.Assert(err, IsNil) - ks = append(ks, k) - } - - err := UpdateKeyDataPCRProtectionPolicy(s.TPM(), authKeys[0], tpm2test.NewPCRProfileFromCurrentValues(tpm2.HashAlgorithmSHA256, []int{7, 23}), ks...) - c.Check(err, ErrorMatches, "invalid key data: key data at index 1 is not related to the primary key data") -}