-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement some additional hierarchy control and dictionary attack functions for TPM2 #109
base: master
Are you sure you want to change the base?
Changes from all commits
4806c07
67499b4
c5ced97
736fbab
e66d769
c6c7cb7
a3814f4
9f5e4eb
6cd31e7
cf23a6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -489,6 +489,121 @@ func CreatePrimaryRawTemplate(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSel | |
return CreatePrimary(rw, owner, sel, parentPassword, ownerPassword, pub) | ||
} | ||
|
||
func encodeClear(hierarchy tpmutil.Handle, password string) ([]byte, error) { | ||
ha, err := tpmutil.Pack(hierarchy) | ||
if err != nil { | ||
return nil, err | ||
} | ||
auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(password)}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return concat(ha, auth) | ||
} | ||
|
||
// Clear removes all context associated with the current owner from the TPM. | ||
// The handle provided must be for the platform or lockout hierarchy. This command will fail if the clear command | ||
// has been disabled via the ClearControl() API. | ||
func Clear(rw io.ReadWriter, hierarchy tpmutil.Handle, password string) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add doc comments to all exported funcs There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
cmd, err := encodeClear(hierarchy, password) | ||
if err != nil { | ||
return err | ||
} | ||
_, err = runCommand(rw, TagSessions, cmdClear, tpmutil.RawBytes(cmd)) | ||
return err | ||
} | ||
|
||
func encodeClearControl(hierarchy tpmutil.Handle, disable bool, password string) ([]byte, error) { | ||
handle, err := tpmutil.Pack(hierarchy) | ||
if err != nil { | ||
return nil, err | ||
} | ||
auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(password)}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
param, err := tpmutil.Pack(disable) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return concat(handle, auth, param) | ||
} | ||
|
||
// ClearControl controls whether the TPM can be cleared with the Clear() API. Calling this with the third | ||
// parameter set to true will disable the ability to clear the TPM. Calling it with the third parameter set to | ||
// false will reenable the ability to clear the TPM. | ||
// | ||
// The handle provided must be for the platform or lockout hierarchy when disabling the ability to clear the | ||
// TPM, but reenabling requires that it be the handle for the platform hierarchy. | ||
func ClearControl(rw io.ReadWriter, hierarchy tpmutil.Handle, disable bool, password string) error { | ||
cmd, err := encodeClearControl(hierarchy, disable, password) | ||
if err != nil { | ||
return err | ||
} | ||
_, err = runCommand(rw, TagSessions, cmdClearControl, tpmutil.RawBytes(cmd)) | ||
return err | ||
} | ||
|
||
func encodeSetDAParameters(maxTries, recoveryTime, lockoutRecovery uint32, password string) ([]byte, error) { | ||
lockout, err := tpmutil.Pack(HandleLockout) | ||
if err != nil { | ||
return nil, err | ||
} | ||
auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(password)}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
params, err := tpmutil.Pack(maxTries, recoveryTime, lockoutRecovery) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return concat(lockout, auth, params) | ||
} | ||
|
||
// SetDictionaryAttackParameters changes the dictionary attack lockout parameters. The first parameter is the | ||
// number of authorization failures before the lockout is enabled. The second parameter is the number of | ||
// seconds before the authorization failure count is decremented by one. Setting this to zero disables | ||
// dictionary attack protection. The third parameter is the number of seconds after a lockout hierarchy | ||
// authorization failure before the lockout hierarchy can be used again. Setting this to zero causes this | ||
// lockout to be cleared after a power cycle. | ||
// | ||
// This command must be authorized using the lockout hierarchy. | ||
func SetDictionaryAttackParameters(rw io.ReadWriter, maxTries, recoveryTime, lockoutRecovery uint32, password string) error { | ||
cmd, err := encodeSetDAParameters(maxTries, recoveryTime, lockoutRecovery, password) | ||
if err != nil { | ||
return err | ||
} | ||
_, err = runCommand(rw, TagSessions, cmdDictionaryAttackParameters, tpmutil.RawBytes(cmd)) | ||
return err | ||
} | ||
|
||
func encodeHierarchyChangeAuthParameters(hierarchy tpmutil.Handle, oldPassword, newPassword string) ([]byte, error) { | ||
handle, err := tpmutil.Pack(hierarchy) | ||
if err != nil { | ||
return nil, err | ||
} | ||
auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(oldPassword)}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
params, err := tpmutil.Pack(tpmutil.U16Bytes(newPassword)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return concat(handle, auth, params) | ||
} | ||
|
||
// Change the authorization value for the specified hierarchy. The command must be authorized with the | ||
// hierarchy's current authorization value. | ||
func HierarchyChangeAuth(rw io.ReadWriter, hierarchy tpmutil.Handle, oldPassword, newPassword string) error { | ||
cmd, err := encodeHierarchyChangeAuthParameters(hierarchy, oldPassword, newPassword) | ||
if err != nil { | ||
return err | ||
} | ||
_, err = runCommand(rw, TagSessions, cmdHierarchyChangeAuth, tpmutil.RawBytes(cmd)) | ||
return err | ||
} | ||
|
||
func decodeReadPublic(in []byte) (Public, []byte, []byte, error) { | ||
var resp struct { | ||
Public tpmutil.U16Bytes | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1363,3 +1363,56 @@ func TestCreatePrimaryRawTemplate(t *testing.T) { | |
t.Errorf("got key exponent %v, want %v", pubRSA.E, defaultKeyParams.RSAParameters.Exponent) | ||
} | ||
} | ||
|
||
func TestClear(t *testing.T) { | ||
rw := openTPM(t) | ||
defer rw.Close() | ||
|
||
rootHandle, _, err := CreatePrimary(rw, HandleOwner, pcrSelection7, emptyPassword, emptyPassword, defaultKeyParams) | ||
if err != nil { | ||
t.Fatalf("CreatePrimary failed: %v", err) | ||
} | ||
defer FlushContext(rw, rootHandle) | ||
|
||
persistentHandle := tpmutil.Handle(0x817FFFFF) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment explaining where this value comes from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just copied this value from other tests in tpm2_test.go. |
||
// Evict persistent key, if there is one already (e.g. last test run failed). | ||
if err := EvictControl(rw, emptyPassword, HandleOwner, persistentHandle, persistentHandle); err != nil { | ||
t.Logf("(expected) EvictControl failed: %v", err) | ||
} | ||
// Make key persistent. | ||
if err := EvictControl(rw, emptyPassword, HandleOwner, rootHandle, persistentHandle); err != nil { | ||
t.Fatalf("EvictControl failed: %v", err) | ||
} | ||
|
||
if err := Clear(rw, HandleLockout, emptyPassword); err != nil { | ||
if err := EvictControl(rw, emptyPassword, HandleOwner, persistentHandle, persistentHandle); err != nil { | ||
t.Logf("EvictControl failed: %v", err) | ||
} | ||
t.Fatalf("Clear failed: %v", err) | ||
} | ||
|
||
vals, _, err := GetCapability(rw, CapabilityHandles, 1, uint32(persistentHandle)) | ||
if err != nil { | ||
t.Fatalf("GetCapability failed: %v", err) | ||
} | ||
|
||
if len(vals) != 0 { | ||
t.Errorf("Persistent handle wasn't cleared") | ||
} | ||
} | ||
|
||
func TestHierarchyChangeAuth(t *testing.T) { | ||
rw := openTPM(t) | ||
defer rw.Close() | ||
|
||
if err := HierarchyChangeAuth(rw, HandleOwner, emptyPassword, defaultPassword); err != nil { | ||
t.Fatalf("HierarchyChangeAuth failed: %v", err) | ||
} | ||
defer HierarchyChangeAuth(rw, HandleOwner, defaultPassword, emptyPassword) | ||
|
||
handle, _, err := CreatePrimary(rw, HandleOwner, pcrSelection7, defaultPassword, emptyPassword, defaultKeyParams) | ||
if err != nil { | ||
t.Errorf("CreatePrimary failed: %v", err) | ||
} | ||
FlushContext(rw, handle) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move it one line higher, to keep sorted order
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I've done that now.