Skip to content
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

Windows TPM Base Services (TBS) - Implement Tbsi_Get_OwnerAuth #276

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions tpmutil/tbs/tbs_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ var errorDescriptions = map[Error]string{
ErrOwnerauthNotFound: "The requested TPM OwnerAuth value was not found.",
}

// OwnerAuthType values required by Tbsi_Get_OwnerAuth
// https://docs.microsoft.com/en-us/windows/win32/api/tbs/nf-tbs-tbsi_get_ownerauth
type OwnerAuthType uint32

const (
// FullAuthorization retrieves Full authorization delegation blob
FullAuthorization OwnerAuthType = 1
// Endorsement20Authorization retrieves Endorsement authorization delegation blob (TPM 2.0 only)
Endorsement20Authorization OwnerAuthType = 12
// Storage20Authorization retrieves Storage authorization delegation blob (TPM 2.0 Only)
Storage20Authorization OwnerAuthType = 13
)

// Tbs.dll provides an API for making calls to the TPM:
// https://docs.microsoft.com/en-us/windows/desktop/TBS/tpm-base-services-portal
var (
Expand All @@ -135,6 +148,7 @@ var (
tbsContextClose = tbsDLL.NewProc("Tbsip_Context_Close")
tbsSubmitCommand = tbsDLL.NewProc("Tbsip_Submit_Command")
tbsGetTCGLog = tbsDLL.NewProc("Tbsi_Get_TCG_Log")
tbsGetOwnerAuth = tbsDLL.NewProc("Tbsi_Get_OwnerAuth")
)

// Returns the address of the beginning of a slice or 0 for a nil slice.
Expand Down Expand Up @@ -250,3 +264,26 @@ func (context Context) GetTCGLog(logBuffer []byte) (uint32, error) {
)
return logBufferLen, getError(result)
}

// GetOwnerAuth Retrieves the owner authorization of the TPM if the information is available in the local registry.
// If ownerAuthBuffer is nil, the actual size of the TPM ownerAuth is returned.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not allocate the slice from within this function and return ([]byte, error)?

// ErrOwnerauthNotFound is returned if the requested TPM ownerAuth value was not found. On failure,
// the returned length is unspecified.
// https://docs.microsoft.com/en-us/windows/win32/api/tbs/nf-tbs-tbsi_get_ownerauth
func (context Context) GetOwnerAuth(ownerAuthType OwnerAuthType, ownerAuthBuffer []byte) (uint32, error) {
ownerAuthBufferLen := uint32(len(ownerAuthBuffer))

// TBS_RESULT Tbsi_Get_OwnerAuth(
// TBS_HCONTEXT hContext,
// TBS_OWNERAUTH_TYPE ownerauthType,
// PBYTE pOutputBuf,
// PUINT32 pOutputBufLen
// );
result, _, _ := tbsGetOwnerAuth.Call(
uintptr(context),
uintptr(uint32(ownerAuthType)),
sliceAddress(ownerAuthBuffer),
uintptr(unsafe.Pointer(&ownerAuthBufferLen)),
)
return ownerAuthBufferLen, getError(result)
}
75 changes: 75 additions & 0 deletions tpmutil/tbs/tbs_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,78 @@ func TestSubmitCommandLongResponse(t *testing.T) {
t.Fatalf("Got response of %v, expected %v", rawResponse, expectedGetRandomRawResponse)
}
}

// Get Storage owner authorization delegation blob
func TestGetStorageOwnerAuth(t *testing.T) {
ctx := getContext(t)
defer ctx.Close()

authBufferLength, err := ctx.GetOwnerAuth(Storage20Authorization, nil)
if err == ErrOwnerauthNotFound || err == ErrInternalError {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that this check will only skip the test if the TBS call failed due to lack of admin rights?

expectedErrorHint := "An internal error occurred. Are you running with Administrative permissions?"
if err == ErrOwnerauthNotFound {
expectedErrorHint = "Delegation blob not available in the registry."
}
t.Logf("Skipping retrieval of Storage authorization; %v", expectedErrorHint)
t.SkipNow()
} else if err != nil {
t.Fatalf("Failed to get Storage authorization delegation blob size: %v", err)
}

storageOwnerAuth := make([]byte, authBufferLength)
if _, err := ctx.GetOwnerAuth(Storage20Authorization, storageOwnerAuth); err != nil && err != ErrOwnerauthNotFound {
t.Fatalf("Failed to retrieve Storage Authorization delegation blob from the registry: %v", err)
} else if err == ErrOwnerauthNotFound {
t.Log("Skipping retrieval of Storage authorization; Delegation blob not available in the registry.")
t.SkipNow()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make sense to try using the auth value to make sure it came through correctly (i.e., doesn't need base64 decoded or something)


// Get Endorsement owner authorization delegation blob
func TestGetEndorsementOwnerAuth(t *testing.T) {
ctx := getContext(t)
defer ctx.Close()

authBufferLength, err := ctx.GetOwnerAuth(Endorsement20Authorization, nil)
if err == ErrOwnerauthNotFound || err == ErrInternalError {
expectedErrorHint := "An internal error occurred. Are you running with Administrative permissions?"
if err == ErrOwnerauthNotFound {
expectedErrorHint = "Delegation blob not available in the registry."
}
t.Logf("Skipping retrieval of Endorsement authorization; %v", expectedErrorHint)
t.SkipNow()
} else if err != nil {
t.Fatalf("Unexpected error occurred when retrieving Endorsement authorization delegation blob size: %v", err)
}
if authBufferLength <= 0 {
t.Fatal("Expected positive Endorsement authorization delegation blob size")
}

endorsementOwnerAuth := make([]byte, authBufferLength)
if _, err := ctx.GetOwnerAuth(Endorsement20Authorization, endorsementOwnerAuth); err != nil && err != ErrOwnerauthNotFound {
t.Fatalf("Failed to retrieve Endorsement Authorization delegation blob from the registry: %v", err)
}
}

// Get Full owner authorization delegation blob
func TestGetFullOwnerAuth(t *testing.T) {
ctx := getContext(t)
defer ctx.Close()

authBufferLength, err := ctx.GetOwnerAuth(FullAuthorization, nil)
if err == ErrOwnerauthNotFound || err == ErrInternalError {
expectedErrorHint := "An internal error occurred. Are you running with Administrative permissions?"
if err == ErrOwnerauthNotFound {
expectedErrorHint = "Delegation blob not available in the registry."
}
t.Logf("Skipping retrieval of Full authorization; %v", expectedErrorHint)
t.SkipNow()
} else if err != nil {
t.Fatalf("Unexpected error occurred when retrieving Full authorization delegation blob size: %v", err)
}

fullOwnerAuth := make([]byte, authBufferLength)
if _, err := ctx.GetOwnerAuth(FullAuthorization, fullOwnerAuth); err != nil && err != ErrOwnerauthNotFound {
t.Fatalf("Failed to retrieve Full Authorization delegation blob from the registry: %v", err)
}
}