Add a fake Intel CBnT image
This commit is contained in:
parent
733ae38177
commit
9c65fff579
|
@ -52,9 +52,7 @@ func (opts getRegistersOptions) Config() (getRegistersConfig, error) {
|
|||
}
|
||||
|
||||
// GetRegisters extracts status registers.
|
||||
func GetRegisters(
|
||||
options ...GetRegistersOption,
|
||||
) (registers.Registers, error) {
|
||||
func GetRegisters(options ...GetRegistersOption) (registers.Registers, error) {
|
||||
cfg, err := getRegistersOptions(options).Config()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid arguments: %w", err)
|
||||
|
|
9
go.mod
9
go.mod
|
@ -3,9 +3,11 @@ module github.com/9elements/converged-security-suite/v2
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/9elements/converged-security-suite/v2/testdata/firmware v0.0.0-00010101000000-000000000000
|
||||
github.com/9elements/go-linux-lowlevel-hw v0.0.0-20211215141225-8375dd201aae
|
||||
github.com/alecthomas/kong v0.2.11
|
||||
github.com/creasty/defaults v1.5.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e
|
||||
github.com/edsrzf/mmap-go v1.0.0
|
||||
github.com/fearful-symmetry/gomsr v0.0.1
|
||||
|
@ -17,12 +19,17 @@ require (
|
|||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/linuxboot/fiano v1.0.6-0.20220208095308-e3fa29a6b2aa
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/marcoguerri/go-tpm-tcti v0.0.0-20210425104733-8e8c8fe68e60
|
||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/pretty v1.0.2
|
||||
github.com/tjfoc/gmsm v1.4.1
|
||||
github.com/ulikunitz/xz v0.5.10
|
||||
github.com/xaionaro-facebook/go-dmidecode v0.0.0-20220413144237-c42d5bef2498
|
||||
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9
|
||||
github.com/xaionaro-go/unsafetools v0.0.0-20210722164218-75ba48cf7b3c
|
||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
||||
replace github.com/9elements/converged-security-suite/v2/testdata/firmware => ./testdata/firmware
|
||||
|
|
17
go.sum
17
go.sum
|
@ -131,6 +131,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
|||
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
|
@ -303,14 +305,14 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linuxboot/fiano v1.0.4-0.20220119141046-2f62e2f75b44 h1:b8Cu/qf9K+BNPReLHARMtpz9uXFz6wZ6ysriJ76qbWc=
|
||||
github.com/linuxboot/fiano v1.0.4-0.20220119141046-2f62e2f75b44/go.mod h1:lsLW5PqsAN0OvdhI6SBszDwTF16ab8wfVPpewsQBOu8=
|
||||
github.com/linuxboot/fiano v1.0.6-0.20220208095308-e3fa29a6b2aa h1:EdI6AWh797oO1RTEngQegbeIThWRddsGKN75TfKWC7U=
|
||||
github.com/linuxboot/fiano v1.0.6-0.20220208095308-e3fa29a6b2aa/go.mod h1:lsLW5PqsAN0OvdhI6SBszDwTF16ab8wfVPpewsQBOu8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/marcoguerri/go-tpm-tcti v0.0.0-20210425104733-8e8c8fe68e60 h1:6ZzceIckZYWVOe7mshJNP0VbCHovX6KUuARRLqjeM0Q=
|
||||
github.com/marcoguerri/go-tpm-tcti v0.0.0-20210425104733-8e8c8fe68e60/go.mod h1:wD5IzQ+Bhi6Nj20Vb3TFPvJKTZbGo/hu1Yhr44rUcx4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
|
@ -459,6 +461,8 @@ github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066/go.mod h1:FS
|
|||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810/go.mod h1:dF0BBJ2YrV1+2eAIyEI+KeSidgA6HqoIP1u5XTlMq/o=
|
||||
github.com/xaionaro-facebook/go-dmidecode v0.0.0-20220413144237-c42d5bef2498 h1:DungyLUCAeepf9LlCgBufekeSdeonRFkiMxzNIz2ZzM=
|
||||
github.com/xaionaro-facebook/go-dmidecode v0.0.0-20220413144237-c42d5bef2498/go.mod h1:II0+Quqf1lG4nq4udbG0Jn3uvbUlrCL4iccqrN5XRjY=
|
||||
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9 h1:LZsotURuIwV1yjhoaTpbdZHf0/7QtWtvXH8VZ4zs/ug=
|
||||
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9/go.mod h1:op5hoGu7YbHB+PlxrR0jAhl5OaCpYCEqtdCfusfZCYk=
|
||||
github.com/xaionaro-go/gosrc v0.0.0-20201124181305-3fdf8476a735/go.mod h1:KWPOUqeg7VZ8gE4MQJJmG+YgmNf2yAkBiDI++R48tFg=
|
||||
|
@ -498,8 +502,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as=
|
||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -641,8 +646,9 @@ golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea h1:+WiDlPBBaO+h9vPNZi8uJ3k4BkKQB7Iow3aqwHVA5hI=
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0W+hLtAhkV1tPsXhutqs=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
@ -815,8 +821,9 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -111,3 +111,20 @@ type ErrUnknownVendorType struct{}
|
|||
func (err *ErrUnknownVendorType) Error() string {
|
||||
return "unable to find an appropriate PCD parser for the firmware image"
|
||||
}
|
||||
|
||||
// ErrTooDummyFirmwareVersionFiles means there were found too many files
|
||||
// with the GUID used exclusively in dummy firmwares we invented. There
|
||||
// should be only one such file in a dummy firmware.
|
||||
type ErrTooDummyFirmwareVersionFiles struct{}
|
||||
|
||||
func (err *ErrTooDummyFirmwareVersionFiles) Error() string {
|
||||
return "too many version files of a dummy firmware"
|
||||
}
|
||||
|
||||
// ErrDummyFirmwareVersionFileWrongType means the version file of a dummy
|
||||
// firmware is not a file.
|
||||
type ErrDummyFirmwareVersionFileWrongType struct{}
|
||||
|
||||
func (err *ErrDummyFirmwareVersionFileWrongType) Error() string {
|
||||
return "version file of a dummy firmware is not a file"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package pcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
pkgbytes "github.com/linuxboot/fiano/pkg/bytes"
|
||||
"github.com/linuxboot/fiano/pkg/guid"
|
||||
"github.com/linuxboot/fiano/pkg/uefi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
addFirmwareParser(ParseFirmwareDummy)
|
||||
}
|
||||
|
||||
// ParseFirmwareDummy is a variant of ParseFirmware for dummy firmware,
|
||||
// generated by ../../testdata/firmware/scripts/generate_fake_intel_firmware.sh
|
||||
func ParseFirmwareDummy(
|
||||
firmwareImage FirmwareImage,
|
||||
) (ParsedFirmware, error) {
|
||||
firmwareVersionFileGUID := *guid.MustParse("658ABE96-545D-4797-BDCC-B9BE16AAD5EE")
|
||||
nodes, err := firmwareImage.GetByGUID(firmwareVersionFileGUID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse the firmware: %w", err)
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(nodes) > 1 {
|
||||
return nil, &ErrTooDummyFirmwareVersionFiles{}
|
||||
}
|
||||
node := nodes[0]
|
||||
file, ok := node.Firmware.(*uefi.File)
|
||||
if !ok {
|
||||
return nil, &ErrDummyFirmwareVersionFileWrongType{}
|
||||
}
|
||||
return &ParsedFirmwareGeneric{
|
||||
FirmwareImage: firmwareImage,
|
||||
FirmwareVendorVersionCodeRanges: pkgbytes.Ranges{{
|
||||
Offset: node.Offset,
|
||||
Length: uint64(len(node.Buf())),
|
||||
}},
|
||||
FirmwareVendorVersionRanges: pkgbytes.Ranges{{
|
||||
Offset: node.Offset + file.DataOffset,
|
||||
Length: uint64(len(node.Buf())) - file.DataOffset,
|
||||
}},
|
||||
FirmwareVendorVersionFFSGUID: firmwareVersionFileGUID,
|
||||
}, nil
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
package firmware
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed fake_intel_firmware.fd
|
||||
var FakeIntelFirmware []byte
|
|
@ -0,0 +1,7 @@
|
|||
module github.com/9elements/converged-security-suite/v2/testdata/firmware
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/ulikunitz/xz v0.5.10
|
||||
|
||||
replace github.com/9elements/converged-security-suite/v2/ => ../../
|
|
@ -0,0 +1,2 @@
|
|||
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
@ -0,0 +1,227 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is how we create a dummy image:
|
||||
# * Create BIOS region.
|
||||
# * Create dummy NVAR, PEI and DXE volumes inside the region.
|
||||
# * Create FIT (which is a one more layout table, independent to UEFI layout, but works in the same space) inside a padding inside DXE.
|
||||
# * Inject KM and BPM.
|
||||
#
|
||||
# * It access FIT to get access to ACM, BPM and KM.
|
||||
# * Then it executes ACM and uses BPM to jump to PEI.
|
||||
# * Then PEI parses the UEFI layout and after pre-EFI initialization jumps to DXE.
|
||||
#
|
||||
# Also in real images usually:
|
||||
# * FIT, FIT pointer, legacy reset vector, KM, BPM and microcodes are placed in paddings in DXE.
|
||||
# * ACM is placed into a padding between PEI and DXE.
|
||||
|
||||
# == Parsing arguments ==
|
||||
|
||||
errorExit() {
|
||||
ERROR="$1"; shift
|
||||
echo "error: $ERROR" >&2
|
||||
echo "syntax $0 <output_file>" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
OUTPUT_FILE="$1"; shift
|
||||
if [[ "$OUTPUT_FILE" = "" ]]; then
|
||||
errorExit "no output file entered"
|
||||
fi
|
||||
|
||||
if [[ -e "$OUTPUT_FILE" ]]; then
|
||||
errorExit "'$OUTPUT_FILE' already exists, exiting to avoid overwriting"
|
||||
fi
|
||||
|
||||
# == Initializing the process ==
|
||||
|
||||
set -e
|
||||
|
||||
FBSOURCE="$HOME/fbsource"
|
||||
|
||||
declare -A DEPENDENCIES
|
||||
setDependency() {
|
||||
PATH_VARIABLE_NAME="$1"; shift
|
||||
IMPORT_PATH="$1"; shift
|
||||
if [[ "$IMPORT_PATH" = "" || "$PATH_VARIABLE_NAME" = "" ]]; then
|
||||
errorExit "an empty dependency value ('$IMPORT_PATH' '$PATH_VARIABLE_NAME')"
|
||||
fi
|
||||
if [[ "${DEPENDENCIES[$PATH_VARIABLE_NAME]}" != "" ]]; then
|
||||
errorExit "overwriting dependencies for $PATH_VARIABLE_NAME"
|
||||
fi
|
||||
go install "$IMPORT_PATH" >/dev/null 2>/dev/null &
|
||||
DEPENDENCIES[$PATH_VARIABLE_NAME]="$IMPORT_PATH"
|
||||
}
|
||||
|
||||
prepareDependencies() {
|
||||
wait
|
||||
GO_PATH_BIN="$(go env GOPATH | awk -F ':' '{print $1}')"/bin
|
||||
for PATH_VARIABLE_NAME in "${!DEPENDENCIES[@]}"; do
|
||||
IMPORT_PATH="${DEPENDENCIES[$PATH_VARIABLE_NAME]}"
|
||||
BINARY_NAME="$(echo "$IMPORT_PATH" | sed -e 's%.*/%%g')"
|
||||
BINARY_PATH="$GO_PATH_BIN/$BINARY_NAME"
|
||||
eval "$PATH_VARIABLE_NAME=\"\$BINARY_PATH\""
|
||||
done
|
||||
}
|
||||
|
||||
setDependency UTK github.com/linuxboot/fiano/cmds/utk
|
||||
setDependency CBNTPROV github.com/9elements/converged-security-suite/v2/cmd/cbnt-prov
|
||||
setDependency PCR0TOOL github.com/9elements/converged-security-suite/v2/cmd/pcr0tool
|
||||
setDependency FITTOOL github.com/linuxboot/fiano/cmds/fittool
|
||||
|
||||
prepareDependencies
|
||||
|
||||
|
||||
# createVolumeWithPadFile creates a volume with a pad file inside.
|
||||
#
|
||||
# A a pad file is important, because `fwtest` does benign injections by corrupting
|
||||
# the last byte of a first pad file. And we need the second one to
|
||||
createVolumeWithPadFile() {
|
||||
OFFSET="$1"; shift
|
||||
SIZE="$1"; shift
|
||||
UUID="$1"; shift
|
||||
|
||||
# Creating a volume with a pid file inside of size 256 bytes
|
||||
$UTK -erase-polarity 0xFF "$OUTPUT_FILE" \
|
||||
create-fv "$OFFSET" "$SIZE" "$UUID" \
|
||||
insert pad_file 256 end "$UUID" \
|
||||
save "$OUTPUT_FILE"
|
||||
}
|
||||
|
||||
# insertRawFile insert a raw file to a volume with a defined content
|
||||
insertRawFile() {
|
||||
VOLUME_GUID="$1"; shift
|
||||
FILE_GUID="$1"; shift
|
||||
CONTENT="$1"; shift
|
||||
|
||||
if [[ "${#CONTENT}" -ge 248 ]]; then
|
||||
errorExit "big file content is not supported yet"
|
||||
fi
|
||||
|
||||
FILE_SIZE="$((${#CONTENT} + 24))" # len(content) + len(headers)
|
||||
$UTK "$OUTPUT_FILE" insert file <(
|
||||
# == HEADERS ==
|
||||
|
||||
# GUID
|
||||
IFS=- FILE_GUID_PARTS=($FILE_GUID)
|
||||
PART_IDX=0
|
||||
for PART in ${FILE_GUID_PARTS[@]}; do
|
||||
# reverse:
|
||||
if [[ $PART_IDX -lt 3 ]]; then
|
||||
PART=$(echo "$PART"| xxd -p -r | xxd -e -g 256 -u | awk '{print $2}')
|
||||
fi
|
||||
PART_IDX=$(($PART_IDX + 1))
|
||||
# write:
|
||||
echo -n "$PART" | xxd -r -p
|
||||
done
|
||||
# Checksums. Forcing to zero for simplicity
|
||||
echo -n "00 00" | xxd -r -p
|
||||
# File Type. Raw == 1
|
||||
echo -n "01" | xxd -r -p
|
||||
# Attributes
|
||||
echo -n "00" | xxd -r -p
|
||||
# Size
|
||||
echo -n "$(printf "%02X" "$FILE_SIZE") 00 00" | xxd -r -p
|
||||
# File state. Forcing to zero for simplicity
|
||||
echo -n "00" | xxd -r -p
|
||||
|
||||
# == CONTENT ==
|
||||
|
||||
echo -n "$CONTENT"
|
||||
) end "$VOLUME_GUID" save "$OUTPUT_FILE"
|
||||
}
|
||||
|
||||
# == Creating the image ==
|
||||
|
||||
# Create an empty image.
|
||||
dd if=/dev/zero of="$OUTPUT_FILE" bs=1K count=64 2>/dev/null
|
||||
|
||||
# Create a PEI volume at offset 32K of size 32K.
|
||||
#
|
||||
# UUID "61C0F511-A691-4F54-974F-B9A42172CE53" is taken from PEI of a real UEFI image.
|
||||
createVolumeWithPadFile $((32 * 1024)) $((32 * 1024)) "61C0F511-A691-4F54-974F-B9A42172CE53"
|
||||
|
||||
# Also inserting a file to PEI which would be used to store PCD data.
|
||||
# Here we generated just a random UUID for it and then will reuse this in "parse_firmware_dummy.go".
|
||||
insertRawFile "61C0F511-A691-4F54-974F-B9A42172CE53" "658ABE96-545D-4797-BDCC-B9BE16AAD5EE" "dummy-firmware"
|
||||
|
||||
# Create a DXE volume at offset 4K of size 16K.
|
||||
#
|
||||
# UUID "5C60F367-A505-419A-859E-2A4FF6CA6FE5" is taken from DXE of a real UEFI image.
|
||||
createVolumeWithPadFile $((4 * 1024)) $((16 * 1024)) "5C60F367-A505-419A-859E-2A4FF6CA6FE5"
|
||||
|
||||
# Create a NVAR volume at offset 0K of size 4K.
|
||||
#
|
||||
# UUID "FA4974FC-AF1D-4E5D-BDC5-DACD6D27BAEC" is taken from an NVAR volume of a real UEFI image.
|
||||
createVolumeWithPadFile $((0 * 1024)) $((4 * 1024)) "FA4974FC-AF1D-4E5D-BDC5-DACD6D27BAEC"
|
||||
|
||||
# Generate OEM and ODM keys
|
||||
#
|
||||
# Size 2048 was picked arbitrary. Just small enough to generate it fast (and make this script work fast).
|
||||
OEMPRIVKEYPATH="$(mktemp)"
|
||||
ODMPRIVKEYPATH="$(mktemp)"
|
||||
OEMPUBKEYPATH="$(mktemp)"
|
||||
ODMPUBKEYPATH="$(mktemp)"
|
||||
#trap 'rm -f "$OEMPRIVKEYPATH" "$ODMPRIVKEYPATH" "$OEMPUBKEYPATH" "$ODMPUBKEYPATH"' ABRT EXIT INT
|
||||
openssl genpkey -out "$OEMPRIVKEYPATH" -algorithm RSA -pkeyopt rsa_keygen_bits:2048 >/dev/null 2>/dev/null
|
||||
openssl genpkey -out "$ODMPRIVKEYPATH" -algorithm RSA -pkeyopt rsa_keygen_bits:2048 >/dev/null 2>/dev/null
|
||||
openssl rsa -in "$OEMPRIVKEYPATH" -pubout -out "$OEMPUBKEYPATH" 2>/dev/null
|
||||
openssl rsa -in "$ODMPRIVKEYPATH" -pubout -out "$ODMPUBKEYPATH" 2>/dev/null
|
||||
|
||||
# Create FIT at offset 59K.
|
||||
"$FITTOOL" init -f "$OUTPUT_FILE" --pointer-from-offset $(( 59 * 1024 ))
|
||||
|
||||
# Create a dummy ACM
|
||||
DUMMYACMPATH="$(mktemp)"
|
||||
"$CBNTPROV" acm-gen "$DUMMYACMPATH" --moduletype 2 --sesvn 1 --txtsvn 2 --date $((16#11223344)) --size 2048
|
||||
|
||||
# Inject the dummy ACM (FIT entry type 0x02) at offset 20K.
|
||||
# In real images ACM is usually pleaced between PEI and DXE, so we use offset 20K.
|
||||
"$FITTOOL" add_raw_headers -f "$OUTPUT_FILE" --address-offset $(( 20 * 1024 )) --type 2
|
||||
dd if="$DUMMYACMPATH" of="$OUTPUT_FILE" bs=1K seek=20 conv=notrunc 2>/dev/null
|
||||
rm -f "$DUMMYACMPATH"
|
||||
|
||||
# Create a KM.
|
||||
#
|
||||
# KM uses an OEM key to authorize an ODM key to issue a signed BPM. So `km-gen` will calculate
|
||||
# a hash of the ODM (BPM) pubkey and store it inside KM, in turn KM is signed by the OEM (KM) key.
|
||||
#
|
||||
# Algorithm "SHA256" was picked arbitrary. One may use another algorithm.
|
||||
KMPATH="$(mktemp)"
|
||||
# Generated an unsigned KM
|
||||
"$CBNTPROV" km-gen "$KMPATH" "$OEMPUBKEYPATH" --bpmpubkey "$ODMPUBKEYPATH" --pkhashalg=SHA256 --bpmhashalgo SHA256
|
||||
# Sign the KM (with no password on the private key file)
|
||||
"$CBNTPROV" km-sign "$KMPATH" "$KMPATH" "$OEMPRIVKEYPATH" RSASSA ""
|
||||
|
||||
# Inject the KM reference to FIT (FIT entry type 0x0B), by referencing it as at the offset 21K
|
||||
"$FITTOOL" add_raw_headers -f "$OUTPUT_FILE" --address-offset $(( 21 * 1024 )) --size "$(stat -c %s "$KMPATH")" --type $((16#B))
|
||||
dd if="$KMPATH" of="$OUTPUT_FILE" bs=1K seek=21 conv=notrunc 2>/dev/null
|
||||
rm -f "$KMPATH"
|
||||
|
||||
# Create a BPM.
|
||||
#
|
||||
# BPM contains information about the firmware. Including (but not limited to):
|
||||
# * Which areas to measure to PCR registers as IBB.
|
||||
# * Which boot policy to use.
|
||||
# * Security Version Number (SVN).
|
||||
#
|
||||
# BPM is signed by an ODM key, which is trusted, because its hash is included into KM, which is
|
||||
# signed by the OEM key (which we trust, because OEM is us).
|
||||
BPMPATH="$(mktemp)"
|
||||
# `$CBNTPROV bpm-gen` (to generate an BPM) depends on scanning the FIT table of
|
||||
# the image to find BIOS startup modules and include them as IBBs.
|
||||
# So first we need to add at least one entry. We will use a part of the dummy PEI
|
||||
# as an IBB section (similar things also happens in a real image).
|
||||
"$FITTOOL" add_raw_headers -f "$OUTPUT_FILE" --address-offset $((32 * 1024)) --size $((4 * 1024 / 16)) --type $((16#7))
|
||||
# Now we can execute the `$CBNTPROV bpm-gen` command
|
||||
"$CBNTPROV" bpm-gen --ibbhash SHA1,SHA256 "$BPMPATH" "$OUTPUT_FILE"
|
||||
# Sign the BPM (with no password on the private key file)
|
||||
"$CBNTPROV" bpm-sign "$BPMPATH" "$BPMPATH" "$ODMPRIVKEYPATH" RSASSA ""
|
||||
|
||||
# Inject the BPM reference into FIT (FIT entry type 0x0C), by referencing it as at the offset 22K
|
||||
"$FITTOOL" add_raw_headers -f "$OUTPUT_FILE" --address-offset $(( 22 * 1024 )) --size "$(stat -c %s "$BPMPATH")" --type $((16#C))
|
||||
dd if="$BPMPATH" of="$OUTPUT_FILE" bs=1K seek=22 conv=notrunc 2>/dev/null
|
||||
rm -f "$BPMPATH"
|
||||
|
||||
# That's it, a dummy image is ready (and is in "$OUTPUT_FILE") :)
|
||||
"$FITTOOL" show -f "$OUTPUT_FILE"
|
||||
"$PCR0TOOL" printnodes -as-tree "$OUTPUT_FILE"
|
Loading…
Reference in New Issue