Add a fake Intel CBnT image

This commit is contained in:
Dmitrii Okunev 2022-04-20 14:46:44 +01:00 committed by Christopher Meis
parent 733ae38177
commit 9c65fff579
10 changed files with 328 additions and 9 deletions

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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"
}

View 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
}

BIN
testdata/firmware/fake_intel_firmware.fd vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
package firmware
import _ "embed"
//go:embed fake_intel_firmware.fd
var FakeIntelFirmware []byte

7
testdata/firmware/go.mod vendored Normal file
View File

@ -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/ => ../../

2
testdata/firmware/go.sum vendored Normal file
View File

@ -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=

View File

@ -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"