mirror of
https://github.com/matter-labs/vault-auth-tee.git
synced 2025-07-21 15:53:55 +02:00
530 lines
23 KiB
Go
530 lines
23 KiB
Go
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) Matter Labs
|
|
|
|
package vault_auth_tee
|
|
|
|
// #cgo LDFLAGS: -lsgx_dcap_quoteverify -ldl
|
|
/*
|
|
#include <stdlib.h> // for malloc/free
|
|
#include <sgx_dcap_quoteverify.h>
|
|
#include <sgx_quote.h>
|
|
|
|
sgx_ql_qv_supplemental_t *allocSupp() { return (sgx_ql_qv_supplemental_t*) malloc(sizeof(sgx_ql_qv_supplemental_t)); }
|
|
void freeSupp(sgx_ql_qv_supplemental_t * * p) { free(p); }
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"os"
|
|
"unsafe"
|
|
)
|
|
|
|
type TeeQvCollateral struct {
|
|
MajorVersion uint16 `json:"major_version"`
|
|
MinorVersion uint16 `json:"minor_version"`
|
|
TeeType uint32 `json:"tee_type"`
|
|
PckCrlIssuerChain []byte `json:"pck_crl_issuer_chain"`
|
|
RootCaCrl []byte `json:"root_ca_crl"`
|
|
PckCrl []byte `json:"pck_crl"`
|
|
TcbInfoIssuerChain []byte `json:"tcb_info_issuer_chain"`
|
|
TcbInfo []byte `json:"tcb_info"`
|
|
QeIdentityIssuerChain []byte `json:"qe_identity_issuer_chain"`
|
|
QeIdentity []byte `json:"qe_identity"`
|
|
}
|
|
|
|
type Quote struct {
|
|
Version [2]byte `json:"version"`
|
|
KeyType [2]byte `json:"key_type"`
|
|
Reserved [4]byte `json:"reserved"`
|
|
QeSvn [2]byte `json:"qe_svn"`
|
|
PceSvn [2]byte `json:"pce_svn"`
|
|
QeVendorId [16]byte `json:"qe_vendor_id"`
|
|
UserData [20]byte `json:"user_data"`
|
|
ReportBody struct {
|
|
Cpusvn [16]byte `json:"cpusvn"`
|
|
Miscselect [4]byte `json:"miscselect"`
|
|
Reserved1 [28]byte `json:"reserved1"`
|
|
Features [8]byte `json:"features"`
|
|
Xfrm [8]byte `json:"xfrm"`
|
|
MrEnclave [32]byte `json:"mrenclave"`
|
|
Reserved2 [32]byte `json:"reserved2"`
|
|
MrSigner [32]byte `json:"mrsigner"`
|
|
Reserved3 [96]byte `json:"reserved3"`
|
|
IsvProdid [2]byte `json:"isv_prodid"`
|
|
IsvSvn [2]byte `json:"isv_svn"`
|
|
Reserved4 [60]byte `json:"reserved4"`
|
|
ReportData [64]byte `json:"reportdata"`
|
|
} `json:"report_body"`
|
|
}
|
|
|
|
type QuoteVerificationResult struct {
|
|
VerificationResult SgxQlQvResult
|
|
CollateralExpired bool
|
|
EarliestExpirationDate int64
|
|
Advisory string
|
|
Quote Quote
|
|
}
|
|
|
|
// convertCollateral converts TeeQvCollateral to sgx_ql_qve_collateral_t
|
|
func convertQveCollateral(coll C.sgx_ql_qve_collateral_t) TeeQvCollateral {
|
|
var data = TeeQvCollateral{
|
|
TeeType: uint32(coll.tee_type),
|
|
PckCrlIssuerChain: C.GoBytes(unsafe.Pointer(coll.pck_crl_issuer_chain), C.int(coll.pck_crl_issuer_chain_size)),
|
|
RootCaCrl: C.GoBytes(unsafe.Pointer(coll.root_ca_crl), C.int(coll.root_ca_crl_size)),
|
|
PckCrl: C.GoBytes(unsafe.Pointer(coll.pck_crl), C.int(coll.pck_crl_size)),
|
|
TcbInfoIssuerChain: C.GoBytes(unsafe.Pointer(coll.tcb_info_issuer_chain), C.int(coll.tcb_info_issuer_chain_size)),
|
|
TcbInfo: C.GoBytes(unsafe.Pointer(coll.tcb_info), C.int(coll.tcb_info_size)),
|
|
QeIdentityIssuerChain: C.GoBytes(unsafe.Pointer(coll.qe_identity_issuer_chain), C.int(coll.qe_identity_issuer_chain_size)),
|
|
QeIdentity: C.GoBytes(unsafe.Pointer(coll.qe_identity), C.int(coll.qe_identity_size)),
|
|
}
|
|
|
|
// Hack needed due to unnamed union and struct at the beginning
|
|
var pver = (*[2]uint16)(unsafe.Pointer(&coll))
|
|
data.MajorVersion = pver[0]
|
|
data.MinorVersion = pver[1]
|
|
|
|
return data
|
|
}
|
|
|
|
// convertCollateral converts TeeQvCollateral to sgx_ql_qve_collateral_t
|
|
func convertCollateral(coll TeeQvCollateral) C.sgx_ql_qve_collateral_t {
|
|
var data = C.sgx_ql_qve_collateral_t{
|
|
tee_type: C.uint32_t(coll.TeeType),
|
|
pck_crl_issuer_chain: (*C.char)(C.CBytes(coll.PckCrlIssuerChain)),
|
|
pck_crl_issuer_chain_size: C.uint32_t(len(coll.PckCrlIssuerChain)),
|
|
root_ca_crl: (*C.char)(C.CBytes(coll.RootCaCrl)),
|
|
root_ca_crl_size: C.uint32_t(len(coll.RootCaCrl)),
|
|
pck_crl: (*C.char)(C.CBytes(coll.PckCrl)),
|
|
pck_crl_size: C.uint32_t(len(coll.PckCrl)),
|
|
tcb_info_issuer_chain: (*C.char)(C.CBytes(coll.TcbInfoIssuerChain)),
|
|
tcb_info_issuer_chain_size: C.uint32_t(len(coll.TcbInfoIssuerChain)),
|
|
tcb_info: (*C.char)(C.CBytes(coll.TcbInfo)),
|
|
tcb_info_size: C.uint32_t(len(coll.TcbInfo)),
|
|
qe_identity_issuer_chain: (*C.char)(C.CBytes(coll.QeIdentityIssuerChain)),
|
|
qe_identity_issuer_chain_size: C.uint32_t(len(coll.QeIdentityIssuerChain)),
|
|
qe_identity: (*C.char)(C.CBytes(coll.QeIdentity)),
|
|
qe_identity_size: C.uint32_t(len(coll.QeIdentity)),
|
|
}
|
|
|
|
// Hack needed due to unnamed union and struct at the beginning
|
|
var pver = (*[2]uint16)(unsafe.Pointer(&data))
|
|
pver[0] = coll.MajorVersion
|
|
pver[1] = coll.MinorVersion
|
|
|
|
return data
|
|
}
|
|
|
|
type SgxQlQvResult uint32
|
|
|
|
const (
|
|
SgxQlQvResultOk = SgxQlQvResult(C.SGX_QL_QV_RESULT_OK)
|
|
SgxQlQvResultConfigNeeded = SgxQlQvResult(C.SGX_QL_QV_RESULT_CONFIG_NEEDED)
|
|
SgxQlQvResultOutOfDate = SgxQlQvResult(C.SGX_QL_QV_RESULT_OUT_OF_DATE)
|
|
SgxQlQvResultOutOfDateConfigNeeded = SgxQlQvResult(C.SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED)
|
|
SgxQlQvResultInvalidSignature = SgxQlQvResult(C.SGX_QL_QV_RESULT_INVALID_SIGNATURE)
|
|
SgxQlQvResultRevoked = SgxQlQvResult(C.SGX_QL_QV_RESULT_REVOKED)
|
|
SgxQlQvResultUnspecified = SgxQlQvResult(C.SGX_QL_QV_RESULT_UNSPECIFIED)
|
|
SgxQlQvResultSwHardeningNeeded = SgxQlQvResult(C.SGX_QL_QV_RESULT_SW_HARDENING_NEEDED)
|
|
SgxQlQvResultConfigAndSwHardeningNeeded = SgxQlQvResult(C.SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED)
|
|
)
|
|
|
|
var (
|
|
// ErrEmptyReport is returned by VerifyRemoteReport if reportBytes is empty.
|
|
ErrEmptyReport = errors.New("empty report")
|
|
ErrSgxQlErrorUnexpected = errors.New("SGX_QL_ERROR_UNEXPECTED")
|
|
ErrSgxQlErrorInvalidParameter = errors.New("SGX_QL_ERROR_INVALID_PARAMETER")
|
|
ErrSgxQlErrorOutOfMemory = errors.New("SGX_QL_ERROR_OUT_OF_MEMORY")
|
|
ErrSgxQlErrorEcdsaIdMismatch = errors.New("SGX_QL_ERROR_ECDSA_ID_MISMATCH")
|
|
ErrSgxQlPathnameBufferOverflowError = errors.New("SGX_QL_PATHNAME_BUFFER_OVERFLOW_ERROR")
|
|
ErrSgxQlFileAccessError = errors.New("SGX_QL_FILE_ACCESS_ERROR")
|
|
ErrSgxQlErrorStoredKey = errors.New("SGX_QL_ERROR_STORED_KEY")
|
|
ErrSgxQlErrorPubKeyIdMismatch = errors.New("SGX_QL_ERROR_PUB_KEY_ID_MISMATCH")
|
|
ErrSgxQlErrorInvalidPceSigScheme = errors.New("SGX_QL_ERROR_INVALID_PCE_SIG_SCHEME")
|
|
ErrSgxQlAttKeyBlobError = errors.New("SGX_QL_ATT_KEY_BLOB_ERROR")
|
|
ErrSgxQlUnsupportedAttKeyId = errors.New("SGX_QL_UNSUPPORTED_ATT_KEY_ID")
|
|
ErrSgxQlUnsupportedLoadingPolicy = errors.New("SGX_QL_UNSUPPORTED_LOADING_POLICY")
|
|
ErrSgxQlInterfaceUnavailable = errors.New("SGX_QL_INTERFACE_UNAVAILABLE")
|
|
ErrSgxQlPlatformLibUnavailable = errors.New("SGX_QL_PLATFORM_LIB_UNAVAILABLE")
|
|
ErrSgxQlAttKeyNotInitialized = errors.New("SGX_QL_ATT_KEY_NOT_INITIALIZED")
|
|
ErrSgxQlAttKeyCertDataInvalid = errors.New("SGX_QL_ATT_KEY_CERT_DATA_INVALID")
|
|
ErrSgxQlNoPlatformCertData = errors.New("SGX_QL_NO_PLATFORM_CERT_DATA")
|
|
ErrSgxQlOutOfEpc = errors.New("SGX_QL_OUT_OF_EPC")
|
|
ErrSgxQlErrorReport = errors.New("SGX_QL_ERROR_REPORT")
|
|
ErrSgxQlEnclaveLost = errors.New("SGX_QL_ENCLAVE_LOST")
|
|
ErrSgxQlInvalidReport = errors.New("SGX_QL_INVALID_REPORT")
|
|
ErrSgxQlEnclaveLoadError = errors.New("SGX_QL_ENCLAVE_LOAD_ERROR")
|
|
ErrSgxQlUnableToGenerateQeReport = errors.New("SGX_QL_UNABLE_TO_GENERATE_QE_REPORT")
|
|
ErrSgxQlKeyCertifcationError = errors.New("SGX_QL_KEY_CERTIFCATION_ERROR")
|
|
ErrSgxQlNetworkError = errors.New("SGX_QL_NETWORK_ERROR")
|
|
ErrSgxQlMessageError = errors.New("SGX_QL_MESSAGE_ERROR")
|
|
ErrSgxQlNoQuoteCollateralData = errors.New("SGX_QL_NO_QUOTE_COLLATERAL_DATA")
|
|
ErrSgxQlQuoteCertificationDataUnsupported = errors.New("SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED")
|
|
ErrSgxQlQuoteFormatUnsupported = errors.New("SGX_QL_QUOTE_FORMAT_UNSUPPORTED")
|
|
ErrSgxQlUnableToGenerateReport = errors.New("SGX_QL_UNABLE_TO_GENERATE_REPORT")
|
|
ErrSgxQlQeReportInvalidSignature = errors.New("SGX_QL_QE_REPORT_INVALID_SIGNATURE")
|
|
ErrSgxQlQeReportUnsupportedFormat = errors.New("SGX_QL_QE_REPORT_UNSUPPORTED_FORMAT")
|
|
ErrSgxQlPckCertUnsupportedFormat = errors.New("SGX_QL_PCK_CERT_UNSUPPORTED_FORMAT")
|
|
ErrSgxQlPckCertChainError = errors.New("SGX_QL_PCK_CERT_CHAIN_ERROR")
|
|
ErrSgxQlTcbinfoUnsupportedFormat = errors.New("SGX_QL_TCBINFO_UNSUPPORTED_FORMAT")
|
|
ErrSgxQlTcbinfoMismatch = errors.New("SGX_QL_TCBINFO_MISMATCH")
|
|
ErrSgxQlQeidentityUnsupportedFormat = errors.New("SGX_QL_QEIDENTITY_UNSUPPORTED_FORMAT")
|
|
ErrSgxQlQeidentityMismatch = errors.New("SGX_QL_QEIDENTITY_MISMATCH")
|
|
ErrSgxQlTcbOutOfDate = errors.New("SGX_QL_TCB_OUT_OF_DATE")
|
|
ErrSgxQlTcbOutOfDateConfigurationNeeded = errors.New("SGX_QL_TCB_OUT_OF_DATE_CONFIGURATION_NEEDED")
|
|
ErrSgxQlSgxEnclaveIdentityOutOfDate = errors.New("SGX_QL_SGX_ENCLAVE_IDENTITY_OUT_OF_DATE")
|
|
ErrSgxQlSgxEnclaveReportIsvsvnOutOfDate = errors.New("SGX_QL_SGX_ENCLAVE_REPORT_ISVSVN_OUT_OF_DATE")
|
|
ErrSgxQlQeIdentityOutOfDate = errors.New("SGX_QL_QE_IDENTITY_OUT_OF_DATE")
|
|
ErrSgxQlSgxTcbInfoExpired = errors.New("SGX_QL_SGX_TCB_INFO_EXPIRED")
|
|
ErrSgxQlSgxPckCertChainExpired = errors.New("SGX_QL_SGX_PCK_CERT_CHAIN_EXPIRED")
|
|
ErrSgxQlSgxCrlExpired = errors.New("SGX_QL_SGX_CRL_EXPIRED")
|
|
ErrSgxQlSgxSigningCertChainExpired = errors.New("SGX_QL_SGX_SIGNING_CERT_CHAIN_EXPIRED")
|
|
ErrSgxQlSgxEnclaveIdentityExpired = errors.New("SGX_QL_SGX_ENCLAVE_IDENTITY_EXPIRED")
|
|
ErrSgxQlPckRevoked = errors.New("SGX_QL_PCK_REVOKED")
|
|
ErrSgxQlTcbRevoked = errors.New("SGX_QL_TCB_REVOKED")
|
|
ErrSgxQlTcbConfigurationNeeded = errors.New("SGX_QL_TCB_CONFIGURATION_NEEDED")
|
|
ErrSgxQlUnableToGetCollateral = errors.New("SGX_QL_UNABLE_TO_GET_COLLATERAL")
|
|
ErrSgxQlErrorInvalidPrivilege = errors.New("SGX_QL_ERROR_INVALID_PRIVILEGE")
|
|
ErrSgxQlNoQveIdentityData = errors.New("SGX_QL_NO_QVE_IDENTITY_DATA")
|
|
ErrSgxQlCrlUnsupportedFormat = errors.New("SGX_QL_CRL_UNSUPPORTED_FORMAT")
|
|
ErrSgxQlQeidentityChainError = errors.New("SGX_QL_QEIDENTITY_CHAIN_ERROR")
|
|
ErrSgxQlTcbinfoChainError = errors.New("SGX_QL_TCBINFO_CHAIN_ERROR")
|
|
ErrSgxQlErrorQvlQveMismatch = errors.New("SGX_QL_ERROR_QVL_QVE_MISMATCH")
|
|
ErrSgxQlTcbSwHardeningNeeded = errors.New("SGX_QL_TCB_SW_HARDENING_NEEDED")
|
|
ErrSgxQlTcbConfigurationAndSwHardeningNeeded = errors.New("SGX_QL_TCB_CONFIGURATION_AND_SW_HARDENING_NEEDED")
|
|
ErrSgxQlUnsupportedMode = errors.New("SGX_QL_UNSUPPORTED_MODE")
|
|
ErrSgxQlNoDevice = errors.New("SGX_QL_NO_DEVICE")
|
|
ErrSgxQlServiceUnavailable = errors.New("SGX_QL_SERVICE_UNAVAILABLE")
|
|
ErrSgxQlNetworkFailure = errors.New("SGX_QL_NETWORK_FAILURE")
|
|
ErrSgxQlServiceTimeout = errors.New("SGX_QL_SERVICE_TIMEOUT")
|
|
ErrSgxQlErrorBusy = errors.New("SGX_QL_ERROR_BUSY")
|
|
ErrSgxQlUnknownMessageResponse = errors.New("SGX_QL_UNKNOWN_MESSAGE_RESPONSE")
|
|
ErrSgxQlPersistentStorageError = errors.New("SGX_QL_PERSISTENT_STORAGE_ERROR")
|
|
ErrSgxQlErrorMessageParsingError = errors.New("SGX_QL_ERROR_MESSAGE_PARSING_ERROR")
|
|
ErrSgxQlPlatformUnknown = errors.New("SGX_QL_PLATFORM_UNKNOWN")
|
|
ErrSgxQlUnknownApiVersion = errors.New("SGX_QL_UNKNOWN_API_VERSION")
|
|
ErrSgxQlCertsUnavailable = errors.New("SGX_QL_CERTS_UNAVAILABLE")
|
|
ErrSgxQlQveidentityMismatch = errors.New("SGX_QL_QVEIDENTITY_MISMATCH")
|
|
ErrSgxQlQveOutOfDate = errors.New("SGX_QL_QVE_OUT_OF_DATE")
|
|
ErrSgxQlPswNotAvailable = errors.New("SGX_QL_PSW_NOT_AVAILABLE")
|
|
ErrSgxQlCollateralVersionNotSupported = errors.New("SGX_QL_COLLATERAL_VERSION_NOT_SUPPORTED")
|
|
ErrSgxQlTdxModuleMismatch = errors.New("SGX_QL_TDX_MODULE_MISMATCH")
|
|
ErrSgxQlQeidentityNotFound = errors.New("SGX_QL_QEIDENTITY_NOT_FOUND")
|
|
ErrSgxQlTcbinfoNotFound = errors.New("SGX_QL_TCBINFO_NOT_FOUND")
|
|
ErrSgxQlInternalServerError = errors.New("SGX_QL_INTERNAL_SERVER_ERROR")
|
|
ErrSgxQlSupplementalDataVersionNotSupported = errors.New("SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED")
|
|
ErrSgxQlRootCaUntrusted = errors.New("SGX_QL_ROOT_CA_UNTRUSTED")
|
|
ErrSgxQlTcbNotSupported = errors.New("SGX_QL_TCB_NOT_SUPPORTED")
|
|
)
|
|
|
|
// convert an SGX quote library error to a go error
|
|
func sgx2Error(err uint32) error {
|
|
switch err {
|
|
case C.SGX_QL_ERROR_UNEXPECTED:
|
|
return ErrSgxQlErrorUnexpected
|
|
case C.SGX_QL_ERROR_INVALID_PARAMETER:
|
|
return ErrSgxQlErrorInvalidParameter
|
|
case C.SGX_QL_ERROR_OUT_OF_MEMORY:
|
|
return ErrSgxQlErrorOutOfMemory
|
|
case C.SGX_QL_ERROR_ECDSA_ID_MISMATCH:
|
|
return ErrSgxQlErrorEcdsaIdMismatch
|
|
case C.SGX_QL_PATHNAME_BUFFER_OVERFLOW_ERROR:
|
|
return ErrSgxQlPathnameBufferOverflowError
|
|
case C.SGX_QL_FILE_ACCESS_ERROR:
|
|
return ErrSgxQlFileAccessError
|
|
case C.SGX_QL_ERROR_STORED_KEY:
|
|
return ErrSgxQlErrorStoredKey
|
|
case C.SGX_QL_ERROR_PUB_KEY_ID_MISMATCH:
|
|
return ErrSgxQlErrorPubKeyIdMismatch
|
|
case C.SGX_QL_ERROR_INVALID_PCE_SIG_SCHEME:
|
|
return ErrSgxQlErrorInvalidPceSigScheme
|
|
case C.SGX_QL_ATT_KEY_BLOB_ERROR:
|
|
return ErrSgxQlAttKeyBlobError
|
|
case C.SGX_QL_UNSUPPORTED_ATT_KEY_ID:
|
|
return ErrSgxQlUnsupportedAttKeyId
|
|
case C.SGX_QL_UNSUPPORTED_LOADING_POLICY:
|
|
return ErrSgxQlUnsupportedLoadingPolicy
|
|
case C.SGX_QL_INTERFACE_UNAVAILABLE:
|
|
return ErrSgxQlInterfaceUnavailable
|
|
case C.SGX_QL_PLATFORM_LIB_UNAVAILABLE:
|
|
return ErrSgxQlPlatformLibUnavailable
|
|
case C.SGX_QL_ATT_KEY_NOT_INITIALIZED:
|
|
return ErrSgxQlAttKeyNotInitialized
|
|
case C.SGX_QL_ATT_KEY_CERT_DATA_INVALID:
|
|
return ErrSgxQlAttKeyCertDataInvalid
|
|
case C.SGX_QL_NO_PLATFORM_CERT_DATA:
|
|
return ErrSgxQlNoPlatformCertData
|
|
case C.SGX_QL_OUT_OF_EPC:
|
|
return ErrSgxQlOutOfEpc
|
|
case C.SGX_QL_ERROR_REPORT:
|
|
return ErrSgxQlErrorReport
|
|
case C.SGX_QL_ENCLAVE_LOST:
|
|
return ErrSgxQlEnclaveLost
|
|
case C.SGX_QL_INVALID_REPORT:
|
|
return ErrSgxQlInvalidReport
|
|
case C.SGX_QL_ENCLAVE_LOAD_ERROR:
|
|
return ErrSgxQlEnclaveLoadError
|
|
case C.SGX_QL_UNABLE_TO_GENERATE_QE_REPORT:
|
|
return ErrSgxQlUnableToGenerateQeReport
|
|
case C.SGX_QL_KEY_CERTIFCATION_ERROR:
|
|
return ErrSgxQlKeyCertifcationError
|
|
case C.SGX_QL_NETWORK_ERROR:
|
|
return ErrSgxQlNetworkError
|
|
case C.SGX_QL_MESSAGE_ERROR:
|
|
return ErrSgxQlMessageError
|
|
case C.SGX_QL_NO_QUOTE_COLLATERAL_DATA:
|
|
return ErrSgxQlNoQuoteCollateralData
|
|
case C.SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED:
|
|
return ErrSgxQlQuoteCertificationDataUnsupported
|
|
case C.SGX_QL_QUOTE_FORMAT_UNSUPPORTED:
|
|
return ErrSgxQlQuoteFormatUnsupported
|
|
case C.SGX_QL_UNABLE_TO_GENERATE_REPORT:
|
|
return ErrSgxQlUnableToGenerateReport
|
|
case C.SGX_QL_QE_REPORT_INVALID_SIGNATURE:
|
|
return ErrSgxQlQeReportInvalidSignature
|
|
case C.SGX_QL_QE_REPORT_UNSUPPORTED_FORMAT:
|
|
return ErrSgxQlQeReportUnsupportedFormat
|
|
case C.SGX_QL_PCK_CERT_UNSUPPORTED_FORMAT:
|
|
return ErrSgxQlPckCertUnsupportedFormat
|
|
case C.SGX_QL_PCK_CERT_CHAIN_ERROR:
|
|
return ErrSgxQlPckCertChainError
|
|
case C.SGX_QL_TCBINFO_UNSUPPORTED_FORMAT:
|
|
return ErrSgxQlTcbinfoUnsupportedFormat
|
|
case C.SGX_QL_TCBINFO_MISMATCH:
|
|
return ErrSgxQlTcbinfoMismatch
|
|
case C.SGX_QL_QEIDENTITY_UNSUPPORTED_FORMAT:
|
|
return ErrSgxQlQeidentityUnsupportedFormat
|
|
case C.SGX_QL_QEIDENTITY_MISMATCH:
|
|
return ErrSgxQlQeidentityMismatch
|
|
case C.SGX_QL_TCB_OUT_OF_DATE:
|
|
return ErrSgxQlTcbOutOfDate
|
|
case C.SGX_QL_TCB_OUT_OF_DATE_CONFIGURATION_NEEDED:
|
|
return ErrSgxQlTcbOutOfDateConfigurationNeeded
|
|
case C.SGX_QL_SGX_ENCLAVE_IDENTITY_OUT_OF_DATE:
|
|
return ErrSgxQlSgxEnclaveIdentityOutOfDate
|
|
case C.SGX_QL_SGX_ENCLAVE_REPORT_ISVSVN_OUT_OF_DATE:
|
|
return ErrSgxQlSgxEnclaveReportIsvsvnOutOfDate
|
|
case C.SGX_QL_QE_IDENTITY_OUT_OF_DATE:
|
|
return ErrSgxQlQeIdentityOutOfDate
|
|
case C.SGX_QL_SGX_TCB_INFO_EXPIRED:
|
|
return ErrSgxQlSgxTcbInfoExpired
|
|
case C.SGX_QL_SGX_PCK_CERT_CHAIN_EXPIRED:
|
|
return ErrSgxQlSgxPckCertChainExpired
|
|
case C.SGX_QL_SGX_CRL_EXPIRED:
|
|
return ErrSgxQlSgxCrlExpired
|
|
case C.SGX_QL_SGX_SIGNING_CERT_CHAIN_EXPIRED:
|
|
return ErrSgxQlSgxSigningCertChainExpired
|
|
case C.SGX_QL_SGX_ENCLAVE_IDENTITY_EXPIRED:
|
|
return ErrSgxQlSgxEnclaveIdentityExpired
|
|
case C.SGX_QL_PCK_REVOKED:
|
|
return ErrSgxQlPckRevoked
|
|
case C.SGX_QL_TCB_REVOKED:
|
|
return ErrSgxQlTcbRevoked
|
|
case C.SGX_QL_TCB_CONFIGURATION_NEEDED:
|
|
return ErrSgxQlTcbConfigurationNeeded
|
|
case C.SGX_QL_UNABLE_TO_GET_COLLATERAL:
|
|
return ErrSgxQlUnableToGetCollateral
|
|
case C.SGX_QL_ERROR_INVALID_PRIVILEGE:
|
|
return ErrSgxQlErrorInvalidPrivilege
|
|
case C.SGX_QL_NO_QVE_IDENTITY_DATA:
|
|
return ErrSgxQlNoQveIdentityData
|
|
case C.SGX_QL_CRL_UNSUPPORTED_FORMAT:
|
|
return ErrSgxQlCrlUnsupportedFormat
|
|
case C.SGX_QL_QEIDENTITY_CHAIN_ERROR:
|
|
return ErrSgxQlQeidentityChainError
|
|
case C.SGX_QL_TCBINFO_CHAIN_ERROR:
|
|
return ErrSgxQlTcbinfoChainError
|
|
case C.SGX_QL_ERROR_QVL_QVE_MISMATCH:
|
|
return ErrSgxQlErrorQvlQveMismatch
|
|
case C.SGX_QL_TCB_SW_HARDENING_NEEDED:
|
|
return ErrSgxQlTcbSwHardeningNeeded
|
|
case C.SGX_QL_TCB_CONFIGURATION_AND_SW_HARDENING_NEEDED:
|
|
return ErrSgxQlTcbConfigurationAndSwHardeningNeeded
|
|
case C.SGX_QL_UNSUPPORTED_MODE:
|
|
return ErrSgxQlUnsupportedMode
|
|
case C.SGX_QL_NO_DEVICE:
|
|
return ErrSgxQlNoDevice
|
|
case C.SGX_QL_SERVICE_UNAVAILABLE:
|
|
return ErrSgxQlServiceUnavailable
|
|
case C.SGX_QL_NETWORK_FAILURE:
|
|
return ErrSgxQlNetworkFailure
|
|
case C.SGX_QL_SERVICE_TIMEOUT:
|
|
return ErrSgxQlServiceTimeout
|
|
case C.SGX_QL_ERROR_BUSY:
|
|
return ErrSgxQlErrorBusy
|
|
case C.SGX_QL_UNKNOWN_MESSAGE_RESPONSE:
|
|
return ErrSgxQlUnknownMessageResponse
|
|
case C.SGX_QL_PERSISTENT_STORAGE_ERROR:
|
|
return ErrSgxQlPersistentStorageError
|
|
case C.SGX_QL_ERROR_MESSAGE_PARSING_ERROR:
|
|
return ErrSgxQlErrorMessageParsingError
|
|
case C.SGX_QL_PLATFORM_UNKNOWN:
|
|
return ErrSgxQlPlatformUnknown
|
|
case C.SGX_QL_UNKNOWN_API_VERSION:
|
|
return ErrSgxQlUnknownApiVersion
|
|
case C.SGX_QL_CERTS_UNAVAILABLE:
|
|
return ErrSgxQlCertsUnavailable
|
|
case C.SGX_QL_QVEIDENTITY_MISMATCH:
|
|
return ErrSgxQlQveidentityMismatch
|
|
case C.SGX_QL_QVE_OUT_OF_DATE:
|
|
return ErrSgxQlQveOutOfDate
|
|
case C.SGX_QL_PSW_NOT_AVAILABLE:
|
|
return ErrSgxQlPswNotAvailable
|
|
case C.SGX_QL_COLLATERAL_VERSION_NOT_SUPPORTED:
|
|
return ErrSgxQlCollateralVersionNotSupported
|
|
case C.SGX_QL_TDX_MODULE_MISMATCH:
|
|
return ErrSgxQlTdxModuleMismatch
|
|
case C.SGX_QL_QEIDENTITY_NOT_FOUND:
|
|
return ErrSgxQlQeidentityNotFound
|
|
case C.SGX_QL_TCBINFO_NOT_FOUND:
|
|
return ErrSgxQlTcbinfoNotFound
|
|
case C.SGX_QL_INTERNAL_SERVER_ERROR:
|
|
return ErrSgxQlInternalServerError
|
|
case C.SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED:
|
|
return ErrSgxQlSupplementalDataVersionNotSupported
|
|
case C.SGX_QL_ROOT_CA_UNTRUSTED:
|
|
return ErrSgxQlRootCaUntrusted
|
|
case C.SGX_QL_TCB_NOT_SUPPORTED:
|
|
return ErrSgxQlTcbNotSupported
|
|
}
|
|
return ErrSgxQlErrorUnexpected
|
|
}
|
|
|
|
func verifyRemoteReportSGXCollateral(reportBytes []byte, pQuoteCollateral *C.sgx_ql_qve_collateral_t, expirationCheckDate int64) (*QuoteVerificationResult, error) {
|
|
if len(reportBytes) == 0 {
|
|
return nil, ErrEmptyReport
|
|
}
|
|
|
|
var collateralExpirationStatus uint32
|
|
var quoteVerificationResult uint32
|
|
|
|
var pSuppData = C.allocSupp()
|
|
var suppDataDesc = C.tee_supp_data_descriptor_t{
|
|
major_version: 0,
|
|
data_size: C.uint(unsafe.Sizeof(C.sgx_ql_qv_supplemental_t{})),
|
|
p_data: (*C.uchar)(unsafe.Pointer(pSuppData)),
|
|
}
|
|
|
|
var pReportBytes = C.CBytes(reportBytes)
|
|
|
|
res := uint32(C.tee_verify_quote(
|
|
(*C.uint8_t)(pReportBytes),
|
|
C.uint32_t(len(reportBytes)),
|
|
(*C.uint8_t)(unsafe.Pointer(pQuoteCollateral)),
|
|
C.time_t(expirationCheckDate),
|
|
(*C.uint32_t)(&collateralExpirationStatus),
|
|
(*C.sgx_ql_qv_result_t)("eVerificationResult),
|
|
nil,
|
|
&suppDataDesc,
|
|
))
|
|
|
|
if res != C.SGX_QL_SUCCESS {
|
|
return nil, sgx2Error(res)
|
|
}
|
|
|
|
var quote = Quote{}
|
|
var byteReader = bytes.NewReader(reportBytes)
|
|
err := binary.Read(byteReader, binary.BigEndian, "e)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var ret = QuoteVerificationResult{
|
|
VerificationResult: SgxQlQvResult(quoteVerificationResult),
|
|
CollateralExpired: collateralExpirationStatus != 0,
|
|
EarliestExpirationDate: int64(pSuppData.earliest_expiration_date),
|
|
Quote: quote,
|
|
}
|
|
|
|
return &ret, nil
|
|
}
|
|
|
|
// SgxVerifyRemoteReport verifies the SGX attestation report.
|
|
// It needs to connect to servers to collect the collateral material.
|
|
func SgxVerifyRemoteReport(reportBytes []byte, expirationCheckDate int64) (*QuoteVerificationResult, error) {
|
|
if len(reportBytes) == 0 {
|
|
return nil, ErrEmptyReport
|
|
}
|
|
|
|
var pQuoteCollateral *C.uint8_t = nil
|
|
var collateralSize C.uint32_t
|
|
res := uint32(C.tee_qv_get_collateral(
|
|
(*C.uint8_t)(&reportBytes[0]),
|
|
C.uint32_t(len(reportBytes)),
|
|
(**C.uint8_t)(&pQuoteCollateral),
|
|
(*C.uint32_t)(&collateralSize),
|
|
))
|
|
|
|
defer C.tee_qv_free_collateral(pQuoteCollateral)
|
|
|
|
if res != C.SGX_QL_SUCCESS {
|
|
return nil, sgx2Error(res)
|
|
}
|
|
|
|
return verifyRemoteReportSGXCollateral(reportBytes, (*C.sgx_ql_qve_collateral_t)(unsafe.Pointer(pQuoteCollateral)), expirationCheckDate)
|
|
}
|
|
|
|
// SgxVerifyRemoteReportCollateral verifies the report along with the collateral material.
|
|
// It does not need to start an SGX enclave, nor does it need to connect to any server.
|
|
func SgxVerifyRemoteReportCollateral(reportBytes []byte, collateral TeeQvCollateral, expirationCheckDate int64) (*QuoteVerificationResult, error) {
|
|
var quoteCollateral = convertCollateral(collateral)
|
|
|
|
return verifyRemoteReportSGXCollateral(reportBytes, "eCollateral, expirationCheckDate)
|
|
}
|
|
|
|
func SgxGetCollateral(reportBytes []byte) (*TeeQvCollateral, error) {
|
|
var pQuoteCollateral *C.uint8_t = nil
|
|
var collateralSize C.uint32_t
|
|
res := uint32(C.tee_qv_get_collateral(
|
|
(*C.uint8_t)(&reportBytes[0]),
|
|
C.uint32_t(len(reportBytes)),
|
|
(**C.uint8_t)(&pQuoteCollateral),
|
|
(*C.uint32_t)(&collateralSize),
|
|
))
|
|
|
|
defer C.tee_qv_free_collateral(pQuoteCollateral)
|
|
|
|
if res != C.SGX_QL_SUCCESS {
|
|
return nil, sgx2Error(res)
|
|
}
|
|
|
|
coll := convertQveCollateral(*(*C.sgx_ql_qve_collateral_t)(unsafe.Pointer(pQuoteCollateral)))
|
|
|
|
return &coll, nil
|
|
}
|
|
|
|
func sgxGramineGetQuote(reportData []byte) ([]byte, error) {
|
|
// open "/dev/attestation/user_report_data" and write reportData
|
|
if err := os.WriteFile("/dev/attestation/user_report_data", reportData, 0600); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// open "/dev/attestation/quote" and read quote
|
|
quote, err := os.ReadFile("/dev/attestation/quote")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return quote, nil
|
|
}
|
|
|
|
func SgxGetQuote(reportData []byte) ([]byte, error) {
|
|
if len(reportData) > 64 {
|
|
reportData = reportData[:64]
|
|
}
|
|
if len(reportData) < 64 {
|
|
reportData = append(reportData, make([]byte, 64-len(reportData))...)
|
|
}
|
|
// only support Gramine for now
|
|
|
|
// check if "/dev/attestation/user_report_data" and "/dev/attestation/quote" exist
|
|
if _, err := os.Stat("/dev/attestation/user_report_data"); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := os.Stat("/dev/attestation/quote"); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return sgxGramineGetQuote(reportData)
|
|
}
|