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 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

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
}

func (pal *enclaveRuntimePal) Attest(spid string, subscriptionKey string, product uint32, quoteType uint32) (err error) {
	if pal.GetLocalReport == nil {
		return nil
	}

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

	if len(targetInfo) != intelsgx.TargetinfoLength {
		return fmt.Errorf("len(targetInfo) is not %d, but %d", intelsgx.TargetinfoLength, len(targetInfo))
	}

	// get local report of SGX
	report, err := pal.GetLocalReport(targetInfo)
	if err != nil {
		return err
	}
	if len(report) != intelsgx.ReportLength {
		return fmt.Errorf("len(report) is not %d, but %d", intelsgx.ReportLength, len(report))
	}

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

	q := &intelsgx.Quote{}
	if err := restruct.Unpack(quote, binary.LittleEndian, &q); err != nil {
		return err
	}

	// 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)
		return err
	}

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

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

	svc.ShowStatus(status)

	return nil
}