mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-06-05 21:29:39 -04:00
image: reimplement and adapt measurement generation in Go
This commit is contained in:
parent
8e706d6de3
commit
f6d9f91877
31 changed files with 1343 additions and 286 deletions
116
image/measured-boot/extract/extract.go
Normal file
116
image/measured-boot/extract/extract.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package extract
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"debug/pe"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"sort"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/image/measured-boot/pesection"
|
||||
)
|
||||
|
||||
// CopyFrom is a wrapper for systemd-dissect --copy-from.
|
||||
func CopyFrom(dissectToolchain, image, path, output string) error {
|
||||
if dissectToolchain == "" {
|
||||
dissectToolchain = "systemd-dissect"
|
||||
}
|
||||
out, err := exec.Command(dissectToolchain, "--copy-from", image, path, output).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to extract %s from %s: %v\n%s", path, image, err, out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PeSectionReader returns a reader for the named section of a PE file.
|
||||
func PeSectionReader(peFile io.ReaderAt, section string) (io.Reader, error) {
|
||||
f, err := pe.NewFile(peFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
for _, s := range f.Sections {
|
||||
if s.Name == section {
|
||||
return io.LimitReader(s.Open(), int64(s.VirtualSize)), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("section %q not found", section)
|
||||
}
|
||||
|
||||
// PeFileSectionDigests returns the section digests of a PE file.
|
||||
func PeFileSectionDigests(peFile io.ReaderAt) ([]pesection.PESection, error) {
|
||||
f, err := pe.NewFile(peFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
sections := make([]pesection.PESection, len(f.Sections))
|
||||
for i, section := range f.Sections {
|
||||
sectionDigest := sha256.New()
|
||||
sectionReader := section.Open()
|
||||
_, err := io.CopyN(sectionDigest, sectionReader, int64(section.VirtualSize))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sections[i].Name = section.Name
|
||||
sections[i].Size = section.VirtualSize
|
||||
sections[i].Digest = ([32]byte)(sectionDigest.Sum(nil))
|
||||
sections[i].Measure = shouldMeasureSection(section.Name)
|
||||
sections[i].MeasureOrder = sectionMeasureOrder(section.Name)
|
||||
}
|
||||
|
||||
sort.Slice(sections, func(i, j int) bool {
|
||||
if sections[i].Measure != sections[j].Measure {
|
||||
return sections[i].Measure
|
||||
}
|
||||
if sections[i].MeasureOrder == sections[j].MeasureOrder {
|
||||
return sections[i].Name < sections[j].Name
|
||||
}
|
||||
return sections[i].MeasureOrder < sections[j].MeasureOrder
|
||||
})
|
||||
|
||||
return sections, nil
|
||||
}
|
||||
|
||||
var ukiSections = []string{
|
||||
".linux",
|
||||
".osrel",
|
||||
".cmdline",
|
||||
".initrd",
|
||||
".splash",
|
||||
".dtb",
|
||||
// uanme and sbat will be added in systemd-stub >= 254
|
||||
// ".uname",
|
||||
// ".sbat",
|
||||
".pcrsig",
|
||||
".pcrkey",
|
||||
}
|
||||
|
||||
func shouldMeasureSection(name string) bool {
|
||||
for _, section := range ukiSections {
|
||||
if name == section && name != ".pcrsig" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func sectionMeasureOrder(name string) int {
|
||||
for i, section := range ukiSections {
|
||||
if name == section {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue