Skip to content

Commit

Permalink
Merge pull request #2 from jrjatin/main
Browse files Browse the repository at this point in the history
Add abi, proto and testing packages
  • Loading branch information
ivishwesh committed Jul 3, 2023
2 parents d7b77a7 + 4612d58 commit a402d03
Show file tree
Hide file tree
Showing 15 changed files with 2,611 additions and 0 deletions.
888 changes: 888 additions & 0 deletions abi/abi.go

Large diffs are not rendered by default.

145 changes: 145 additions & 0 deletions abi/abi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package abi

import (
"bytes"
"testing"

pb "github.com/google/go-tdx-guest/proto/tdx"
test "github.com/google/go-tdx-guest/testing/testdata"
)

func TestQuoteToProto(t *testing.T) {
_, err := QuoteToProto(test.RawQuote)
if err != nil {
t.Fatal(err)
}
}

func TestQuoteToAbiBytes(t *testing.T) {
quote, err := QuoteToProto(test.RawQuote)
if err != nil {
t.Fatal(err)
}
rawQuote, err := QuoteToAbiBytes(quote)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(test.RawQuote, rawQuote) {
t.Errorf("raw quote bytes got %v. Expected %v", rawQuote, test.RawQuote)
}
}

func TestNilToAbiBytesConversions(t *testing.T) {

if _, err := QuoteToAbiBytes(nil); err != ErrQuoteV4Nil {
t.Error(err)
}
if _, err := signedDataToAbiBytes(nil); err != ErrQuoteV4AuthDataNil {
t.Error(err)
}
if _, err := certificationDataToAbiBytes(nil); err != ErrCertificationDataNil {
t.Error(err)
}
if _, err := qeReportCertificationDataToAbiBytes(nil); err != ErrQeReportCertificationDataNil {
t.Error(err)
}
if _, err := qeAuthDataToAbiBytes(nil); err != ErrQeAuthDataNil {
t.Error(err)
}
if _, err := pckCertificateChainToAbiBytes(nil); err != ErrPckCertChainNil {
t.Error(err)
}
if _, err := TdQuoteBodyToAbiBytes(nil); err != ErrTDQuoteBodyNil {
t.Error(err)
}
if _, err := HeaderToAbiBytes(nil); err != ErrHeaderNil {
t.Error(err)
}
if _, err := EnclaveReportToAbiBytes(nil); err != ErrQeReportNil {
t.Error(err)
}
}

func TestInvalidConversionsToAbiBytes(t *testing.T) {
expectedErrors := []string{
"QuoteV4 invalid: QuoteV4 Header error: header is empty",
"QuoteV4 AuthData invalid: signature size is 0 bytes. Expected 64 bytes",
"certification data invalid: certification data type invalid, got 0, expected 6",
"certification data invalid: certification data type invalid, got 7, expected 6",
"certification data invalid: QE Report certification data error: QE Report certification data is empty",
"QE Report certification data invalid: QE Report error: QE Report is empty",
"QE AuthData invalid: parsed data size is 0 bytes. Expected 1 bytes",
"PCK certificate chain data invalid: PCK certificate chain data type invalid, got 0, expected 5",
"PCK certificate chain data invalid: PCK certificate chain data type invalid, got 7, expected 5",
"PCK certificate chain data invalid: PCK certificate chain size is 0. Expected size 2",
"TD quote body invalid: teeTcbSvn size is 0 bytes. Expected 16 bytes",
"header invalid: version 0 not supported",
"header invalid: version 1 not supported",
"header invalid: attestation key type not supported",
"header invalid: TEE type is not TDX",
"QE Report invalid: cpuSvn size is 0 bytes. Expected 48 bytes",
}
if _, err := QuoteToAbiBytes(&pb.QuoteV4{}); err == nil || err.Error() != expectedErrors[0] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[0])
}
if _, err := signedDataToAbiBytes(&pb.Ecdsa256BitQuoteV4AuthData{}); err == nil || err.Error() != expectedErrors[1] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[1])
}
if _, err := certificationDataToAbiBytes(&pb.CertificationData{}); err == nil || err.Error() != expectedErrors[2] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[2])
}
if _, err := certificationDataToAbiBytes(&pb.CertificationData{CertificateDataType: 7}); err == nil || err.Error() != expectedErrors[3] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[3])
}
if _, err := certificationDataToAbiBytes(&pb.CertificationData{CertificateDataType: qeReportCertificationDataType, Size: 2}); err == nil || err.Error() != expectedErrors[4] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[4])
}
if _, err := qeReportCertificationDataToAbiBytes(&pb.QEReportCertificationData{}); err == nil || err.Error() != expectedErrors[5] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[5])
}
if _, err := qeAuthDataToAbiBytes(&pb.QeAuthData{ParsedDataSize: 1}); err == nil || err.Error() != expectedErrors[6] {

t.Errorf("error found: %v, want error: %s", err, expectedErrors[6])
}
if _, err := pckCertificateChainToAbiBytes(&pb.PCKCertificateChainData{}); err == nil || err.Error() != expectedErrors[7] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[7])
}
if _, err := pckCertificateChainToAbiBytes(&pb.PCKCertificateChainData{CertificateDataType: 7}); err == nil || err.Error() != expectedErrors[8] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[8])
}
if _, err := pckCertificateChainToAbiBytes(&pb.PCKCertificateChainData{CertificateDataType: pckReportCertificationDataType, Size: 2}); err == nil || err.Error() != expectedErrors[9] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[9])
}
if _, err := TdQuoteBodyToAbiBytes(&pb.TDQuoteBody{}); err == nil || err.Error() != expectedErrors[10] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[10])
}
if _, err := HeaderToAbiBytes(&pb.Header{}); err == nil || err.Error() != expectedErrors[11] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[11])
}
if _, err := HeaderToAbiBytes(&pb.Header{Version: 1}); err == nil || err.Error() != expectedErrors[12] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[12])
}
if _, err := HeaderToAbiBytes(&pb.Header{Version: QuoteVersion, AttestationKeyType: 1}); err == nil || err.Error() != expectedErrors[13] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[13])
}
if _, err := HeaderToAbiBytes(&pb.Header{Version: QuoteVersion, AttestationKeyType: AttestationKeyType, TeeType: 0x01}); err == nil || err.Error() != expectedErrors[14] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[14])
}
if _, err := EnclaveReportToAbiBytes(&pb.EnclaveReport{}); err == nil || err.Error() != expectedErrors[15] {
t.Errorf("error found: %v, want error: %s", err, expectedErrors[15])
}
}
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/google/go-tdx-guest

go 1.21

require (
golang.org/x/crypto v0.10.0
google.golang.org/protobuf v1.31.0
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
49 changes: 49 additions & 0 deletions proto/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package proto contains protocol buffers that are exchanged between the client
// and server, as well as convenience configuration definitions for tools.
//
// # Generating Protocol Buffer Code
//
// Anytime the Protocol Buffer definitions change, the generated Go code must be
// regenerated. This can be done with "go generate". Just run:
//
// go generate ./...
//
// Upstream documentation:
// https://developers.google.com/protocol-buffers/docs/reference/go-generated
//
// # Code Generation Dependencies
//
// To generate the Go code, your system must have "protoc" installed. See:
// https://github.com/protocolbuffers/protobuf#protocol-compiler-installation
//
// The "protoc-gen-go" tool must also be installed. To install it, run:
//
// go install google.golang.org/protobuf/cmd/protoc-gen-go
//
// If you see a 'protoc-gen-go: program not found or is not executable' error
// for the 'go generate' command, run the following:
//
// echo 'export PATH=$PATH:$GOPATH/bin' >> $HOME/.bashrc
// source $HOME/.bashrc
//
// If you see 'google/protobuf/wrappers.proto not found', then you need to
// similarly set your PROTOC_INSTALL_DIR environment variable to the protoc
// installation directory which should have the "well-known types" in the
// include subdirectory.
package proto

//go:generate protoc -I$PROTOC_INSTALL_DIR/include -I=. --go_out=. --go_opt=module=github.com/google/go-tdx-guest/proto tdx.proto
165 changes: 165 additions & 0 deletions proto/tdx.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

// Package tdx represents a TDX attestation quote.
package tdx;

option go_package = "github.com/google/go-tdx-guest/proto/tdx";

message QuoteV4 {
// Header of quote structure
Header header = 1; // should be 48 bytes

// TD report by which quote is generated
TDQuoteBody td_quote_body = 2; // should be 584 bytes

// Size of the Quote Signature Data structure
uint32 signed_data_size = 3;

// Quote Signature Data structure.
Ecdsa256BitQuoteV4AuthData signed_data =
4; // The size should be same as signed_data_size

// Extra bytes included to fill the quote buffer
bytes extra_bytes = 5; // These trailing bytes can be ignored
}

message Header {
// Version 4 supported
uint32 version = 1;

// Type of attestation key used by quoting enclave
// Values :
// 2 (ECDSA-256-with-P-256 curve)
// 3 (ECDSA-384-with-P-384 curve) (Currently not supported)
uint32 attestation_key_type = 2;

// TEE for this attestation
// TDX : 0x00000081
uint32 tee_type = 3;

bytes qe_svn = 4; // should be 2 bytes
bytes pce_svn = 5; // should be 2 bytes

// Unique vendor id of QE vendor
bytes qe_vendor_id = 6; // should be 16 bytes

// Custom user defined data
bytes user_data = 7; // should be 20 bytes
}

message TDQuoteBody {
bytes tee_tcb_svn = 1; // should be 16 bytes
bytes mr_seam = 2; // should be 48 bytes
bytes mr_signer_seam = 3; // should be 48 bytes
bytes seam_attributes = 4; // should be 8 bytes
bytes td_attributes = 5; // should be 8 bytes
bytes xfam = 6; // should be 8 bytes
bytes mr_td = 7; // should be 48 bytes
bytes mr_config_id = 8; // should be 48 bytes
bytes mr_owner = 9; // should be 48 bytes
bytes mr_owner_config = 10; // should be 48 bytes
bytes rt_mr0 = 11; // should be 48 bytes
bytes rt_mr1 = 12; // should be 48 bytes
bytes rt_mr2 = 13; // should be 48 bytes
bytes rt_mr3 = 14; // should be 48 bytes
bytes report_data = 15; // should be 64 bytes
}

message Ecdsa256BitQuoteV4AuthData {
// The ECDSA 256-bit signature.
bytes signature = 1; // should be 64 bytes

// The ECDSA 256-bit public key of the attestation key.
bytes ecdsa_attestation_key = 2; // should be 64 bytes

// The certification data.
CertificationData certification_data = 3;
}

message CertificationData {
// Supported values:
// - 1 (PCK identifier: PPID in plain text, CPUSVN and PCESVN)
// - 2 (PCK identifier: PPID encrypted using RSA-2048-OAEP, CPUSVN and PCESVN)
// - 3 (PCK identifier: PPID encrypted using RSA-3072-OAEP, CPUSVN and PCESVN)
// - 4 (PCK Leaf Certificate in plain text, currently not supported)
// - 5 (Concatenated PCK Cert Chain)
// - 6 (QE Report Certification Data)
// - 7 (PLATFORM_MANIFEST, currently not supported)
uint32 certificate_data_type = 1;

// Size of Certification Data field
uint32 size = 2;

// Certification Data Type:
// - 1: Byte array that contains concatenation of PPID, CPUSVN,PCESVN (LE),
// PCEID (LE).
// - 2: Byte array that contains concatenation of PPID encrypted using
// RSA-2048-OAEP, CPUSVN, PCESVN (LE), PCEID (LE).
// - 3: Byte array that contains concatenation of PPID encrypted using
// RSA-3072-OAEP, CPUSVN, PCESVN (LE), PCEID (LE).
// - 4: PCK Leaf Certificate
// - 5: Concatenated PCK Cert Chain (PEM formatted). PCK LeafCert||
// Intermediate CA Cert|| Root CA Cert
//- 6: QE Report Certification Data
//- 7: PLATFORM_MANIFEST (currently not supported)

QEReportCertificationData qe_report_certification_data = 3;
}

message QEReportCertificationData {
EnclaveReport qe_report = 1;
bytes qe_report_signature = 2; // should be 64 bytes
QeAuthData qe_auth_data = 3;
PCKCertificateChainData pck_certificate_chain_data = 4;
}
message PCKCertificateChainData {
// Supported values:
// - 1 (PCK identifier: PPID in plain text, CPUSVN and PCESVN)
// - 2 (PCK identifier: PPID encrypted using RSA-2048-OAEP, CPUSVN and PCESVN)
// - 3 (PCK identifier: PPID encrypted using RSA-3072-OAEP, CPUSVN and PCESVN)
// - 4 (PCK Leaf Certificate in plain text, currently not supported)
// - 5 (Concatenated PCK Cert Chain)
// - 6 (QE Report Certification Data)
// - 7 (PLATFORM_MANIFEST, currently not supported)
uint32 certificate_data_type = 1;

// Size of Certification Data field
uint32 size = 2;
bytes pck_cert_chain = 3;
}

message QeAuthData {
// The parsed data size.
uint32 parsed_data_size = 1; // should be 2 bytes
// The data.
bytes data = 2;
}

message EnclaveReport {
bytes cpu_svn = 1; // should be 16 bytes
uint32 misc_select = 2; // should be 4 bytes
bytes reserved1 = 3; // should be 28 bytes
bytes attributes = 4; // should be 16 bytes
bytes mr_enclave = 5; // should be 32 bytes
bytes reserved2 = 6; // should be 32 bytes
bytes mr_signer = 7; // should be 32 bytes
bytes reserved3 = 8; // should be 96 bytes
uint32 isv_prod_id = 9; // should be 2 bytes
uint32 isv_svn = 10; // should be 2 bytes
bytes reserved4 = 11; // should be 60 bytes
bytes report_data = 12; // should be 64 bytes
}
Loading

0 comments on commit a402d03

Please sign in to comment.