go-tpm-tools
go-tpm-tools copied to clipboard
Add ability to parse db and dbx to return a Database usable for policies
For db additions, this would look more like take an existing Database/empty Database and update with hashes and certificates.
- AddCertificate, AddHash For dbx, we should support reading a dbx update file from https://uefi.org/revocationlistfile that then returns a corresponding Database containing the dbx hashes (and certs, if any). Currently, this is done manually using https://github.com/rhboot/dbxtool.
- ParseDatabaseListFile(updateFile []bytes). This will return a Database object that corresponds to the file. Likely this will only be used for dbx files as I'm not aware of any db files that uses the same update format.
This will allow us to embed raw dbx updates and use them to build policy constants, as well as supply that ability to any users of the policy APIs.
For parsing efivarfs you can look at my library; https://github.com/Foxboron/go-uefi
There is also one from canonical: https://github.com/canonical/go-efilib
Thanks for the suggestion! I'm assuming ReadSignatureDatabase is what we want? https://github.com/Foxboron/go-uefi/blob/3d898a764ffd5107102e161c276a8cca63bcb41e/efi/signature/signature_database.go#L155 We're essentially looking for functionality like https://github.com/rhboot/dbxtool, as we want to pull it from a dbx update file like the ones above.
You don't really need to parse it unless you want to resign it. If you have the Microsoft Key Exchange Key enrolled you can do:
package main
import (
"bytes"
"io"
"log"
"net/http"
"github.com/foxboron/go-uefi/efi"
"github.com/foxboron/go-uefi/efi/attributes"
)
func main() {
response, err := http.Get("https://uefi.org/sites/default/files/resources/dbxupdate_x64.bin")
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
buf := new(bytes.Buffer)
io.Copy(buf, response.Body)
attrs := efi.ValidAttributes["dbx"]
if err := attributes.WriteEfivars("dbx", attrs|attributes.EFI_VARIABLE_APPEND_WRITE, buf.Bytes()); err != nil {
log.Fatal(err)
}
}
If you want to resign it you can do something like this
package main
import (
"bytes"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"github.com/foxboron/go-uefi/efi"
"github.com/foxboron/go-uefi/efi/attributes"
"github.com/foxboron/go-uefi/efi/signature"
"github.com/foxboron/go-uefi/efi/util"
)
func main() {
key := flag.String("key", "", "Key")
cert := flag.String("cert", "", "Certificate")
if len(os.Args) == 1 {
fmt.Println("rewritedbx: -key <key> -cert <cert> [dbx]")
}
response, err := http.Get("https://uefi.org/sites/default/files/resources/dbxupdate_x64.bin")
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
Cert, _ := util.ReadCertFromFile(*cert)
Key, _ := util.ReadKeyFromFile(*key)
buf := new(bytes.Buffer)
io.Copy(buf, response.Body)
// Remove the Authentication header
signature.ReadEFIVariableAuthencation2(buf)
// Get the default Attributes,
// The dbxupdate binary also uses the APPEND_WRITE attribute, so we include that
attrs := efi.ValidAttributes["dbx"] | attributes.EFI_VARIABLE_APPEND_WRITE
// Sign variable
signedBuf, err := efi.SignEFIVariableWithAttr(Key, Cert, "dbx", buf.Bytes(), attrs)
if err != nil {
log.Fatal(err)
}
// Write the variable
if err := attributes.WriteEfivars("dbx", attrs, signedBuf); err != nil {
log.Fatal(err)
}
}
If you want to inspect the list and do any modification you can use ReadSignatureDatabase.
The API might not be perfect, but it works fairly well :)
Right, I see now you want them for policy objects. The above examples might be a bit useless.
For an example parsing the data you can look at my little efianalyze binary: https://github.com/Foxboron/go-uefi/blob/master/cmd/efianalyze/main.go#L95