-
Notifications
You must be signed in to change notification settings - Fork 89
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
Add an initial implementation of parsing event types #108
base: master
Are you sure you want to change the base?
Conversation
Can you please put this in a different package for a bit? This would double the amount of exported API and we've worked hard to get the godoc to be digestible (#63): https://godoc.org/github.com/google/go-attestation/attest With that in mind, I think we can avoid making the user type cast every event back to the type we want. Tom and I were discussing having Parse methods that parsed the event body. e.g.
So the user can iterate through the events and use the corresponding Parse method
|
Sure, though that'll mean exporting rawEvent?
Is this really easier than
? Splitting out the individual parse methods means a lot of basically identical functions, which feels a little less clean than basically doing the same in a switch statement (although for more complex types, we should probably also be exporting information about whether we succeeded in parsing the event) |
You can use the exported Event type :) https://godoc.org/github.com/google/go-attestation/attest#Event I think both strategies are similar amounts of code for the caller. For example to get a single event: events, err := eventlog.ParseEvents(verifiedEvents)
if err != nil {
// ...
}
for _, e := range events {
if pbce, ok := e.(eventlog.PrebootCertEvent); ok {
// use parsed event
}
} vs. for _, e := range events {
if e.Type == eventlog.TypePrebootCertEvent {
pbce, err := eventlog.ParsePrebootCertEvent(e.Data)
if err != nil {
// ...
}
// use parsed event
}
} I suggested the latter because there's a clearer place for users to parse event types that we don't provide a parser for. Either way, I don't think there's a huge difference. Feel free to go with either API |
But EventLog contains an array of rawEvent rather than Event? |
Part of the API design is to require replaying the event log against PCRs before moving forward https://godoc.org/github.com/google/go-attestation/attest#EventLog.Verify We want users of the API to be safe by default, and not mistakenly use something that's not been verified. |
Oh, yes, I see what you mean now. |
4b93759
to
6f41e62
Compare
Ok, added support for Windows event types and tests against a bunch of sample event logs. |
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.
I left some comments, but this PR got a lot bigger before addressing the previous review. To avoid a moving target, can we get the original code merged first? :)
Reviewed the existing files, and will start looking at the events/windows.go
later. Sorry I know the timezone difference isn't helping here.
events/events.go
Outdated
return "" | ||
} | ||
uuid := uuid.UUID{} | ||
if err := uuid.UnmarshalBinary(buf.Bytes()); err != nil { |
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.
Instead of importing a uuid package, please do:
func (d efiGUID) String() string {
data1 := [4]byte{}
data2 := [2]byte{}
data3 := [2]byte{}
binary.BigEndian.PutUint32(data1[:], d.Data1)
binary.BigEndian.PutUint16(data2[:], d.Data2)
binary.BigEndian.PutUint16(data3[:], d.Data3)
return fmt.Sprintf("%x-%x-%x-%x", data1, data2, data3, d.Data4)
}
events/events.go
Outdated
} | ||
|
||
if !bootOption.MatchString(parsedEvent.VariableName) { | ||
return nil |
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.
Why not an error here?
events/events.go
Outdated
return fmt.Errorf("malformed boot variable") | ||
} | ||
|
||
parsedEvent.DevicePathRaw = make([]byte, dplength) |
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.
events/events.go
Outdated
// Check whether there's any optional data | ||
optionaldatalen := len(parsedEvent.VariableData) - dpoffset - int(dplength) | ||
if optionaldatalen > 0 { | ||
parsedEvent.OptionalData = make([]byte, optionaldatalen) |
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.
same dos vector as above
events/events.go
Outdated
if err != nil { | ||
return err | ||
} | ||
parsedEvent.DevicePathRaw = make([]byte, devicePathLength) |
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.
same
events/events.go
Outdated
if err != nil { | ||
return err | ||
} | ||
parsedEvent.Tables = make([]efiConfigurationTable, numTables) |
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.
same dos
events/events.go
Outdated
if err != nil { | ||
return err | ||
} | ||
unicodeName := make([]uint16, header.UnicodeNameLength) |
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.
same dos
events/devicepath.go
Outdated
return fmt.Sprintf("%s(%d,%02x)", prefix, dp.SubType, data[:]) | ||
} | ||
|
||
// efiDevicePath translates an EFI Device Path into the canonical string representation |
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.
got a link for where the canonical representation is specified?
d4551cc
to
fbfc4a7
Compare
There's currently no support for creating application keys on Windows systems. This patch transitions the Windows key type to specifically refer to attestation keys, and reuses the existing wrapped key support for application keys. This allows the creation of keys in the platform store, while still allowing said keys to be manipulated with existing TPM functionality rather than duplicating it.
When generating a new key using a Windows TPM, a `wrappedKey20` was returned, which couldn't be used for signing on Windows, as it's backed by a `windowsTPM`. The `wrappedKey20` seems to be a type specifically aimed at usage with a `wrappedTPM20`, which in turn seems to be used on Linux and for testing, but not when instantiating a TPM on Windows. This commit adds the `newWindowsKey20` function, which returns a key backed by a `windowsTPM`. The key is a `windowsAK20`, now also conforming to the `key` interface, so that it can be used for signing purposes.
My system is returning RCScheme if TPM_ALG_NULL is passed here. This should be causing the key's default scheme to be used, but for some reason it seems unhappy. Just explicitly set the scheme for now to avoid that.
This reverts commit 03018e6.
Raw events aren't enormously helpful. Add an initial implementation of
some of the basic event types - this is largely a scratch proposal so we
can figure out API design.