mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-11 17:04:22 -05:00
117 lines
2.6 KiB
Go
117 lines
2.6 KiB
Go
|
/*
|
||
|
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
|
||
|
}
|