pal_linux.go 3.5 KB
Newer Older
1 2
package enclave_runtime_pal // import "github.com/opencontainers/runc/libenclave/internal/runtime/pal"

3 4 5 6 7 8 9 10 11
/*
#include <sys/prctl.h>

static void workaround_nanosleep(void) {
	// nanosleep() may return the remaining duration longer than
	// requested one due to timer slack.
	prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
}
*/
12 13
import "C"

14
import (
15
	"encoding/binary"
16
	"fmt"
17 18 19 20 21 22
	"github.com/go-restruct/restruct"
	"github.com/opencontainers/runc/libenclave/attestation"
	"github.com/opencontainers/runc/libenclave/attestation/sgx"
	_ "github.com/opencontainers/runc/libenclave/attestation/sgx/ias"
	"github.com/opencontainers/runc/libenclave/intelsgx"
	"log"
23 24 25
	"os"
)

26 27 28 29
const (
	palApiVersion = 2
)

30
func (pal *enclaveRuntimePal) Init(args string, logLevel string) error {
31 32 33
	api := &enclaveRuntimePalApiV1{}
	ver := api.get_version()
	if ver > palApiVersion {
Y
YiLin.Li 已提交
34 35 36
		return fmt.Errorf("unsupported pal api version %d", ver)
	}
	pal.version = ver
37

Y
YiLin.Li 已提交
38
	C.workaround_nanosleep()
39

40
	return api.init(args, logLevel)
41 42 43
}

func (pal *enclaveRuntimePal) Exec(cmd []string, envp []string, stdio [3]*os.File) (int32, error) {
44 45 46 47 48 49
	if pal.version == 1 {
		api := &enclaveRuntimePalApiV1{}
		return api.exec(cmd, envp, stdio)
	}

	api := &enclaveRuntimePalApiV2{}
50
	return api.exec(cmd, envp, stdio)
51 52
}

53 54 55
func (pal *enclaveRuntimePal) Kill(pid int, sig int) error {
	if pal.version == 1 {
		return nil
56
	}
57 58 59

	api := &enclaveRuntimePalApiV2{}
	return api.kill(pid, sig)
60 61 62 63
}

func (pal *enclaveRuntimePal) Destroy() error {
	api := &enclaveRuntimePalApiV1{}
64
	return api.destroy()
65
}
Y
YiLin.Li 已提交
66 67 68 69 70 71 72 73 74

func (pal *enclaveRuntimePal) GetLocalReport(targetInfo []byte) ([]byte, error) {
	if pal.version >= 3 {
		api := &enclaveRuntimePalApiV3{}
		return api.getLocalReport(targetInfo)
	}

	return nil, fmt.Errorf("unsupported pal api version %d", pal.version)
}
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

func parseAttestParameters(spid string, subscriptionKey string, product uint32) map[string]string {
	p := make(map[string]string)

	p["spid"] = spid
	p["subscription-key"] = subscriptionKey
	if product == sgx.ProductEnclave {
		p["service-class"] = "product"
	} else if product == sgx.DebugEnclave {
		p["service-class"] = "dev"
	}

	return p
}

90
func (pal *enclaveRuntimePal) Attest(spid string, subscriptionKey string, product uint32, quoteType uint32) (map[string]string, error) {
91
	if pal.GetLocalReport == nil {
92
		return nil, nil
93 94 95 96
	}

	targetInfo, err := intelsgx.GetQeTargetInfo()
	if err != nil {
97
		return nil, err
98 99 100
	}

	if len(targetInfo) != intelsgx.TargetinfoLength {
101
		return nil, fmt.Errorf("len(targetInfo) is not %d, but %d", intelsgx.TargetinfoLength, len(targetInfo))
102 103 104 105 106
	}

	// get local report of SGX
	report, err := pal.GetLocalReport(targetInfo)
	if err != nil {
107
		return nil, err
108 109
	}
	if len(report) != intelsgx.ReportLength {
110
		return nil, fmt.Errorf("len(report) is not %d, but %d", intelsgx.ReportLength, len(report))
111 112 113 114 115 116 117 118 119
	}

	// get quote from QE(aesmd)
	linkable := false
	if quoteType == intelsgx.QuoteSignatureTypeLinkable {
		linkable = true
	}
	quote, err := intelsgx.GetQuote(report, spid, linkable)
	if err != nil {
120
		return nil, err
121 122 123 124
	}

	q := &intelsgx.Quote{}
	if err := restruct.Unpack(quote, binary.LittleEndian, &q); err != nil {
125
		return nil, err
126 127 128 129 130 131 132 133
	}

	// get IAS remote attestation report
	var verbose bool = true
	p := parseAttestParameters(spid, subscriptionKey, product)
	svc, err := attestation.NewService(p, verbose)
	if err != nil {
		log.Fatal(err)
134
		return nil, err
135 136 137 138
	}

	if err = svc.Check(quote); err != nil {
		log.Fatal(err)
139
		return nil, err
140 141
	}

142
	status, iasReport, err := svc.GetVerifiedReport(quote)
143
	if err != nil {
144
		return nil, fmt.Errorf("%s", err)
145 146 147 148
	}

	svc.ShowStatus(status)

149
	return iasReport, nil
150
}