Skip to content

Commit

Permalink
fix uniqueid and signerid commands if OE_LOG_LEVEL is set
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasten committed Jan 31, 2024
1 parent 36e950c commit 1918bd0
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 42 deletions.
34 changes: 30 additions & 4 deletions ego/cli/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"strings"
)

const oeinfoSectionName = ".oeinfo"

// ErrErrUnsupportedImportEClient is returned when an EGo binary uses the eclient package instead of the enclave package.
var ErrUnsupportedImportEClient = errors.New("unsupported import: github.com/edgelesssys/ego/eclient")

Expand Down Expand Up @@ -95,7 +97,7 @@ func getPayloadInformation(f io.ReaderAt) (uint64, int64, int64, error) {
return 0, 0, 0, err
}

oeInfo := elfFile.Section(".oeinfo")
oeInfo := elfFile.Section(oeinfoSectionName)
if oeInfo == nil {
return 0, 0, 0, ErrNoOEInfo
}
Expand All @@ -113,21 +115,45 @@ func getPayloadInformation(f io.ReaderAt) (uint64, int64, int64, error) {
}

func (c *Cli) getSymbolsFromELF(path string) ([]elf.Symbol, error) {
// Load ELF executable
file, err := c.fs.OpenFile(path, os.O_RDONLY, 0)
file, err := c.fs.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

elfFile, err := elf.NewFile(file)
if err != nil {
return nil, err
}
defer elfFile.Close()

return elfFile.Symbols()
}

func (c *Cli) readDataFromELF(path string, section string, offset int, size int) ([]byte, error) {
file, err := c.fs.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

elfFile, err := elf.NewFile(file)
if err != nil {
return nil, err
}

sec := elfFile.Section(section)
if sec == nil {
return nil, errors.New("section not found")
}

data := make([]byte, size)
if _, err := sec.ReadAt(data, int64(offset)); err != nil {
return nil, err
}

return data, nil
}

// checkUnsupportedImports checks whether the to-be-signed or to-be-executed binary uses Go imports which are not supported.
func (c *Cli) checkUnsupportedImports(path string) error {
symbols, err := c.getSymbolsFromELF(path)
Expand Down
47 changes: 20 additions & 27 deletions ego/cli/signerid.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
package cli

import (
"encoding/json"
"bytes"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"os"
Expand All @@ -18,12 +20,11 @@ import (
"ego/internal/launch"
)

type eradump struct {
SecurityVersion int
ProductID int
UniqueID string
SignerID string
}
const (
offsetSigstruct = 144
offsetModulus = 128
offsetMRENCLAVE = 960
)

func (c *Cli) signeridByKey(path string) (string, error) {
outBytes, err := c.runner.Output(exec.Command(c.getOesignPath(), "signerid", "-k", path))
Expand All @@ -46,37 +47,29 @@ func (c *Cli) signeridByKey(path string) (string, error) {
return "", err
}

func (c *Cli) readEradumpJSONtoStruct(path string) (*eradump, error) {
data, err := c.runner.Output(exec.Command(c.getOesignPath(), "eradump", "-e", path))
if err != nil {
if err, ok := err.(*exec.ExitError); ok {
return nil, errors.New(string(err.Stderr))
}
return nil, err
}

var dump eradump
if err := json.Unmarshal(data, &dump); err != nil {
return nil, err
}
return &dump, nil
}

func (c *Cli) signeridByExecutable(path string) (string, error) {
dump, err := c.readEradumpJSONtoStruct(path)
const modulusSize = 384
modulus, err := c.readDataFromELF(path, oeinfoSectionName, offsetSigstruct+offsetModulus, modulusSize)
if err != nil {
return "", err
}
return dump.SignerID, nil
if bytes.Equal(modulus, make([]byte, modulusSize)) {
// if enclave is unsigned, return all zeros
return strings.Repeat("0", 64), nil
}

// MRSIGNER is the sha256 of the modulus
sum := sha256.Sum256(modulus)
return hex.EncodeToString(sum[:]), nil
}

// Uniqueid returns the UniqueID of a signed executable.
func (c *Cli) Uniqueid(path string) (string, error) {
dump, err := c.readEradumpJSONtoStruct(path)
data, err := c.readDataFromELF(path, oeinfoSectionName, offsetSigstruct+offsetMRENCLAVE, 32)
if err != nil {
return "", err
}
return dump.UniqueID, nil
return hex.EncodeToString(data), nil
}

// Signerid returns the SignerID of a signed executable.
Expand Down
43 changes: 33 additions & 10 deletions ego/cli/signerid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,51 @@ import (

"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestUniqueid(t *testing.T) {
assert := assert.New(t)
require := require.New(t)

cli := NewCli(signeridRunner{}, afero.NewMemMapFs())
fs := afero.Afero{Fs: afero.NewMemMapFs()}
cli := NewCli(nil, fs)
const filename = "foo"

res, err := cli.Uniqueid("foo")
assert.NoError(err)
assert.Equal("uid foo", res)
_, err := cli.Uniqueid(filename)
assert.Error(err)

require.NoError(fs.WriteFile(filename, elfUnsigned, 0))

res, err := cli.Uniqueid(filename)
require.NoError(err)
assert.Equal("0000000000000000000000000000000000000000000000000000000000000000", res)
}

func TestSignerid(t *testing.T) {
func TestSigneridByExecutable(t *testing.T) {
assert := assert.New(t)
require := require.New(t)

cli := NewCli(signeridRunner{}, afero.NewMemMapFs())
fs := afero.Afero{Fs: afero.NewMemMapFs()}
cli := NewCli(nil, fs)
const filename = "foo"

res, err := cli.Signerid("foo")
assert.NoError(err)
assert.Equal("sid foo", res)
_, err := cli.Signerid(filename)
assert.Error(err)

require.NoError(fs.WriteFile(filename, elfUnsigned, 0))

res, err := cli.Signerid(filename)
require.NoError(err)
assert.Equal("0000000000000000000000000000000000000000000000000000000000000000", res)
}

func TestSigneridByKey(t *testing.T) {
assert := assert.New(t)

cli := NewCli(signeridRunner{}, afero.NewMemMapFs())

res, err = cli.Signerid("foo.pem")
res, err := cli.Signerid("foo.pem")
assert.NoError(err)
assert.Equal("id foo.pem", res)
}
Expand Down
15 changes: 14 additions & 1 deletion src/integration_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,22 @@ cp enclave.json /tmp/ego-integration-test/enclave.json
export CGO_ENABLED=0 # test that ego-go ignores this
run ego-go build -o /tmp/ego-integration-test/integration-test

# Sign & run intergration test
# Sign intergration test
cd /tmp/ego-integration-test
run ego sign

# Test id commands
dump=$(ego-oesign dump -e integration-test)
run echo "$dump" | grep "^mrenclave=$(ego uniqueid integration-test)$"
run echo "$dump" | grep "^mrsigner=$(ego signerid integration-test)$"
run echo "$dump" | grep "^mrsigner=$(ego signerid public.pem)$"
export OE_LOG_LEVEL=INFO # regression: id commands were broken with OE_LOG_LEVEL set
run echo "$dump" | grep "^mrenclave=$(ego uniqueid integration-test)$"
run echo "$dump" | grep "^mrsigner=$(ego signerid integration-test)$"
run echo "$dump" | grep "^mrsigner=$(ego signerid public.pem)$"
unset OE_LOG_LEVEL

# Run integration test
run ego run integration-test

# Test heap size check on sign
Expand Down

0 comments on commit 1918bd0

Please sign in to comment.