Skip to content

Commit 9910f21

Browse files
authored
Added TDX Adapter. (intel#10)
1 parent 5c40fa7 commit 9910f21

File tree

12 files changed

+919
-0
lines changed

12 files changed

+919
-0
lines changed

go-client/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type Evidence struct {
3232
Type uint32
3333
Evidence []byte
3434
UserData []byte
35+
EventLog []byte
3536
}
3637

3738
// Config holds the Amber configuration for Client

go-client/token.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func (client *amberClient) GetToken(nonce *Nonce, policyIds []uuid.UUID, evidenc
4343
Nonce: nonce,
4444
UserData: evidence.UserData,
4545
PolicyIds: policyIds,
46+
EventLog: evidence.EventLog,
4647
}
4748

4849
body, err := json.Marshal(tr)

go-tdx/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Intel Project Amber Go TDX Adapter
2+
This is the beta version of Go TDX Adapter for collecting Quote from TDX enabled platform.
3+
4+
This library leverages Intel SGX DCAP for Quote generation: [https://github.com/intel/SGXDataCenterAttestationPrimitives](https://github.com/intel/SGXDataCenterAttestationPrimitives)
5+
6+
## Installation
7+
8+
Install the latest version of the library with the following commands:
9+
10+
```sh
11+
go get github.com/intel/amber-client/go-tdx
12+
```
13+
14+
## Go Requirement
15+
16+
Use <b>go1.17 or newer</b>.
17+
18+
## Usage
19+
20+
Create a new Go TDX adapter, then use the adapter to
21+
collect quote from TDX enabled platform.
22+
23+
```go
24+
import "github.com/intel/amber-client/go-tdx"
25+
26+
evLogParser := tdx.NewEventLogParser()
27+
adapter, err := tdx.NewAdapter(tdHeldData, evLogParser)
28+
if err != nil {
29+
return err
30+
}
31+
32+
evidence, err := adapter.CollectEvidence(nonce)
33+
if err != nil {
34+
return err
35+
}
36+
```
37+
38+
### To decrypt an encrypted blob
39+
40+
```go
41+
em := &tdx.EncryptionMetadata{
42+
PrivateKeyLocation: privateKeyPath,
43+
}
44+
decryptedData, err := tdx.Decrypt(encryptedData, em)
45+
if err != nil {
46+
fmt.Printf("Something bad happened: %s\n\n", err)
47+
return err
48+
}
49+
```
50+
51+
### To collect event log from TD
52+
53+
```go
54+
evLogParser := tdx.NewEventLogParser()
55+
eventLog, err := evLogParser.GetEventLogs()
56+
if err != nil {
57+
return err
58+
}
59+
```
60+
61+
## License
62+
63+
This library is distributed under the BSD-style license found in the [LICENSE](../LICENSE)
64+
file.

go-tdx/collect_evidence.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (c) 2022 Intel Corporation
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
package tdx
7+
8+
// #cgo CFLAGS: -fstack-protector-strong
9+
// #cgo LDFLAGS: -ltdx_attest -L/usr/lib/x86_64-linux-gnu/
10+
//
11+
// #include <stdlib.h>
12+
// #include "tdx_attest.h"
13+
import "C"
14+
import (
15+
"crypto/sha512"
16+
"encoding/json"
17+
"unsafe"
18+
19+
"github.com/intel/amber/v1/client"
20+
"github.com/pkg/errors"
21+
log "github.com/sirupsen/logrus"
22+
)
23+
24+
// CollectEvidence is used to get TDX quote using DCAP Quote Generation service
25+
func (adapter *TdxAdapter) CollectEvidence(nonce []byte) (*client.Evidence, error) {
26+
27+
hash := sha512.New()
28+
_, err := hash.Write(nonce)
29+
if err != nil {
30+
return nil, err
31+
}
32+
_, err = hash.Write(adapter.uData)
33+
if err != nil {
34+
return nil, err
35+
}
36+
reportData := hash.Sum(nil)
37+
38+
cReportData := [64]C.uint8_t{}
39+
for i := 0; i < len(reportData); i++ {
40+
cReportData[i] = C.uint8_t(reportData[i])
41+
}
42+
43+
// tdxReportData holds the reportdata provided as input from attested app
44+
tdxReportData := &C.tdx_report_data_t{d: cReportData}
45+
46+
// selectedAttKeyId holds the default key id used for generating quote
47+
var selectedAttKeyId C.tdx_uuid_t
48+
49+
var quoteSize C.uint32_t
50+
var quoteBuf *C.uint8_t
51+
52+
ret := C.tdx_att_get_quote(tdxReportData, nil, 0, &selectedAttKeyId, &quoteBuf, &quoteSize, 0)
53+
if ret != 0 {
54+
return nil, errors.Errorf("tdx_att_get_quote return error code %x", ret)
55+
}
56+
57+
quote := C.GoBytes(unsafe.Pointer(quoteBuf), C.int(quoteSize))
58+
59+
ret = C.tdx_att_free_quote(quoteBuf)
60+
if ret != 0 {
61+
log.Warnf("tdx_att_free_quote return error code %x", ret)
62+
}
63+
64+
var eventLog []byte
65+
if adapter.EvLogParser != nil {
66+
rtmrEventLogs, err := adapter.EvLogParser.GetEventLogs()
67+
if err != nil {
68+
return nil, errors.Wrap(err, "There was an error while collecting RTMR Event Log Data")
69+
}
70+
71+
eventLog, err = json.Marshal(rtmrEventLogs)
72+
if err != nil {
73+
return nil, errors.Wrap(err, "Error while marshalling RTMR Event Log Data")
74+
}
75+
}
76+
77+
return &client.Evidence{
78+
Type: 1,
79+
Evidence: quote,
80+
UserData: adapter.uData,
81+
EventLog: eventLog,
82+
}, nil
83+
}

go-tdx/decrypt.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2022 Intel Corporation
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
package tdx
7+
8+
import (
9+
"crypto/rand"
10+
"crypto/rsa"
11+
"crypto/sha256"
12+
"crypto/x509"
13+
"encoding/pem"
14+
"io/ioutil"
15+
16+
"github.com/pkg/errors"
17+
)
18+
19+
// EncryptionMetadata holds information around encryption mechanism, e.g., algorithm and key used for encryption
20+
type EncryptionMetadata struct {
21+
Algorithm string
22+
PrivateKey *rsa.PrivateKey
23+
PrivateKeyLocation string
24+
}
25+
26+
// Decrypt is used to decryt the encrypted data based on provided encryption metadata
27+
func Decrypt(encryptedData []byte, em *EncryptionMetadata) ([]byte, error) {
28+
priv := em.PrivateKey
29+
if priv == nil {
30+
// If Private key is not provided, read private key from file
31+
privateKey, err := ioutil.ReadFile(em.PrivateKeyLocation)
32+
if err != nil {
33+
return nil, errors.Wrap(err, "Error reading private key from file")
34+
}
35+
36+
privateKeyBlock, _ := pem.Decode(privateKey)
37+
priv, err = x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
38+
if err != nil {
39+
return nil, errors.Wrap(err, "Error decoding private key")
40+
}
41+
}
42+
43+
decryptedData, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, encryptedData, nil)
44+
if err != nil {
45+
return nil, errors.Wrap(err, "Error while decrypting data")
46+
}
47+
48+
return decryptedData, nil
49+
}

go-tdx/event_log.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Copyright (c) 2022 Intel Corporation
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
package tdx
7+
8+
// These variables can be used by integrators to override the default
9+
// behavior of event-log parsing. By default, the file paths are empty
10+
// and the Application will attempt to read event logs from /sys/firmware.
11+
//
12+
// However, in some environments (ex. embedded linux), /sys/firmware may not
13+
// be available. In these scenarios, an integrator can compile the application
14+
// with go build flags and specify a file containing TCG event-log data.
15+
// For example...
16+
// env CGO_CFLAGS_ALLOW="-f.*" go build -ldflags "-X github.com/go-module/eventlog.uefiEventLogFile=/tmp/myuefieventlogs.bin"
17+
var (
18+
uefiEventLogFile = ""
19+
)
20+
21+
const (
22+
TdelFileLength = 56
23+
TdelSignature = "TDEL"
24+
AcpiTablePath = "/sys/firmware/acpi/tables/"
25+
AcpiTableDataPath = "/sys/firmware/acpi/tables/data/"
26+
TdelPath = AcpiTablePath + TdelSignature
27+
TdelDataPath = AcpiTableDataPath + TdelSignature
28+
)
29+
30+
const (
31+
Uint8Size = 1
32+
Uint16Size = 2
33+
Uint32Size = 4
34+
Uint64Size = 8
35+
ExtDataElementOffset = 92
36+
// Uefi Event Info
37+
UefiBaseOffset = 48
38+
UefiSizeOffset = 40
39+
// Event types
40+
Event80000001 = 0x80000001
41+
Event80000002 = 0x80000002
42+
Event80000007 = 0x80000007
43+
Event8000000A = 0x8000000A
44+
Event8000000B = 0x8000000B
45+
Event8000000C = 0x8000000C
46+
Event80000010 = 0x80000010
47+
Event800000E0 = 0x800000E0
48+
Event00000007 = 0x00000007
49+
Event00000001 = 0x00000001
50+
Event00000003 = 0x00000003
51+
Event00000005 = 0x00000005
52+
Event0000000A = 0x0000000A
53+
Event0000000C = 0x0000000C
54+
Event00000012 = 0x00000012
55+
Event00000010 = 0x00000010
56+
Event00000011 = 0x00000011
57+
EV_IPL = 0x0000000D
58+
// SHA Types
59+
SHA256 = "SHA256"
60+
SHA384 = "SHA384"
61+
SHA512 = "SHA512"
62+
SM3_256 = "SM3_256"
63+
// Algorithm Types
64+
AlgSHA256 = 0xb
65+
AlgSHA384 = 0xc
66+
AlgSHA512 = 0xd
67+
AlgSM3_256 = 0x12
68+
NullUnicodePoint = "\u0000"
69+
)
70+
71+
// EventNameList - define map for event name
72+
var eventNameList = map[uint32]string{
73+
0x00000000: "EV_PREBOOT_CERT",
74+
0x00000001: "EV_POST_CODE",
75+
0x00000002: "EV_UNUSED",
76+
0x00000003: "EV_NO_ACTION",
77+
0x00000004: "EV_SEPARATOR",
78+
0x00000005: "EV_ACTION",
79+
0x00000006: "EV_EVENT_TAG",
80+
0x00000007: "EV_S_CRTM_CONTENTS",
81+
0x00000008: "EV_S_CRTM_VERSION",
82+
0x00000009: "EV_CPU_MICROCODE",
83+
0x0000000A: "EV_PLATFORM_CONFIG_FLAGS",
84+
0x0000000B: "EV_TABLE_OF_DEVICES",
85+
0x0000000C: "EV_COMPACT_HASH",
86+
0x0000000D: "EV_IPL",
87+
0x0000000E: "EV_IPL_PARTITION_DATA",
88+
0x0000000F: "EV_NONHOST_CODE",
89+
0x00000010: "EV_NONHOST_CONFIG",
90+
0x00000011: "EV_NONHOST_INFO",
91+
0x00000012: "EV_OMIT_BOOT_DEVICE_EVENTS",
92+
0x80000000: "EV_EFI_EVENT_BASE",
93+
0x80000001: "EV_EFI_VARIABLE_DRIVER_CONFIG",
94+
0x80000002: "EV_EFI_VARIABLE_BOOT",
95+
0x80000003: "EV_EFI_BOOT_SERVICES_APPLICATION",
96+
0x80000004: "EV_EFI_BOOT_SERVICES_DRIVER",
97+
0x80000005: "EV_EFI_RUNTIME_SERVICES_DRIVER",
98+
0x80000006: "EV_EFI_GPT_EVENT",
99+
0x80000007: "EV_EFI_ACTION",
100+
0x80000008: "EV_EFI_PLATFORM_FIRMWARE_BLOB",
101+
0x80000009: "EV_EFI_HANDOFF_TABLES",
102+
0x8000000A: "EV_EFI_PLATFORM_FIRMWARE_BLOB2",
103+
0x8000000B: "EV_EFI_HANDOFF_TABLES2",
104+
0x8000000C: "EV_EFI_VARIABLE_BOOT2",
105+
0x80000010: "EV_EFI_HCRTM_EVENT",
106+
0x800000E0: "EV_EFI_VARIABLE_AUTHORITY",
107+
0x800000E1: "EV_EFI_SPDM_FIRMWARE_BLOB",
108+
0x800000E2: "EV_EFI_SPDM_FIRMWARE_CONFIG",
109+
}
110+
111+
// RtmrEventLog structure is used to hold complete event log info
112+
type RtmrEventLog struct {
113+
Rtmr RtmrData `json:"rtmr"`
114+
RtmrEvents []RtmrEvent `json:"rtmr_events"`
115+
}
116+
117+
// RtmrData structure is used to hold rtmr info
118+
type RtmrData struct {
119+
Index uint32 `json:"index"`
120+
Bank string `json:"bank"`
121+
}
122+
123+
// RtmrEvent structure is used to hold RTMR Event Info
124+
type RtmrEvent struct {
125+
TypeID string `json:"type_id"`
126+
TypeName string `json:"type_name,omitempty"`
127+
Tags []string `json:"tags,omitempty"`
128+
Measurement string `json:"measurement"`
129+
}
130+
131+
// TcgPcrEventV2 structure represents TCG_PCR_EVENT2 of Intel TXT spec rev16.2
132+
type tcgPcrEventV2 struct {
133+
PcrIndex uint32
134+
EventType uint32
135+
Digest tpmlDigestValue
136+
EventSize uint32
137+
Event []uint8
138+
}
139+
140+
// TpmlDigestValue structure represents TPML_DIGEST_VALUES of Intel TXT spec rev16.2
141+
type tpmlDigestValue struct {
142+
Count uint32
143+
Digests []tpmtHA
144+
}
145+
146+
// TpmtHA structure represents TPMT_HA of Intel TXT spec rev16.2
147+
type tpmtHA struct {
148+
HashAlg uint16
149+
DigestData []byte
150+
}
151+
152+
// TcgPcrEventV1 structure represents TCG_PCR_EVENT of Intel TXT spec rev16.2
153+
type tcgPcrEventV1 struct {
154+
PcrIndex uint32
155+
EventType uint32
156+
Digest [20]byte
157+
EventSize uint32
158+
Event []uint8
159+
}
160+
161+
// UefiGUID structure represents UEFI_GUID of TCG PC Client Platform Firmware Profile spec rev22
162+
type uefiGUID struct {
163+
Data1 uint32
164+
Data2 uint16
165+
Data3 uint16
166+
Data4 [8]uint8
167+
}
168+
169+
// UefiVariableData structure represents UEFI_GUID of TCG PC Client Platform Firmware Profile spec rev22
170+
type uefiVariableData struct {
171+
VariableName uefiGUID
172+
UnicodeNameLength uint64
173+
VariableDataLength uint64
174+
UnicodeName []uint16
175+
VariableData []int8 // Driver or platform-specific data
176+
}

0 commit comments

Comments
 (0)