From 1b051da32e45adf06500309afad02f881eaf0d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Wei=C3=9Fe?= <66256922+daniel-weisse@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:33:22 +0200 Subject: [PATCH] fix: don't sign quotes including added OE header (#718) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel Weiße --- coordinator/clientapi/clientapi.go | 5 +++-- coordinator/clientapi/clientapi_test.go | 26 ++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/coordinator/clientapi/clientapi.go b/coordinator/clientapi/clientapi.go index 05c2d6ea..9689f5d1 100644 --- a/coordinator/clientapi/clientapi.go +++ b/coordinator/clientapi/clientapi.go @@ -785,12 +785,13 @@ func (a *ClientAPI) verifyAndSignQuote( ) (signature []byte, tcbStatus string, err error) { // Add OE quote header if it is not present // e.g. we are dealing with a raw SGX quote generated by Gramine or Occlum + oeQuote := quote if util.IsRawSGXQuote(quote) { - quote = util.AddOEQuoteHeader(quote) + oeQuote = util.AddOEQuoteHeader(quote) } // Verify the quote - report, err := verify(quote) + report, err := verify(oeQuote) if err != nil && !errors.Is(err, attestation.ErrTCBLevelInvalid) { return nil, "", &QuoteVerifyError{err} } diff --git a/coordinator/clientapi/clientapi_test.go b/coordinator/clientapi/clientapi_test.go index c00a4e3f..2fd484a9 100644 --- a/coordinator/clientapi/clientapi_test.go +++ b/coordinator/clientapi/clientapi_test.go @@ -13,6 +13,7 @@ import ( "crypto/sha256" "crypto/x509" "encoding/base64" + "encoding/binary" "encoding/json" "encoding/pem" "errors" @@ -709,23 +710,42 @@ func TestSetManifest(t *testing.T) { func TestSignQuote(t *testing.T) { testCases := map[string]struct { store *fakeStoreTransaction + quote []byte verifyFunc func([]byte) (attestation.Report, error) wantErr bool wantQuoteVerifyErr bool }{ "success": { + quote: []byte("quote"), store: &fakeStoreTransaction{}, verifyFunc: func([]byte) (attestation.Report, error) { return attestation.Report{}, nil }, }, "success with non standard TCB status": { + quote: []byte("quote"), store: &fakeStoreTransaction{}, verifyFunc: func([]byte) (attestation.Report, error) { return attestation.Report{TCBStatus: tcbstatus.OutOfDate}, attestation.ErrTCBLevelInvalid }, }, + "success with raw SGX quote": { + quote: func() []byte { + quote := make([]byte, 64) + binary.LittleEndian.PutUint16(quote[0:2], 3) + binary.LittleEndian.PutUint16(quote[2:4], 3) + binary.LittleEndian.PutUint32(quote[4:8], 0) + binary.LittleEndian.PutUint16(quote[8:10], 42) + binary.LittleEndian.PutUint16(quote[10:12], 42) + return quote + }(), + store: &fakeStoreTransaction{}, + verifyFunc: func([]byte) (attestation.Report, error) { + return attestation.Report{}, nil + }, + }, "quote verification fails": { + quote: []byte("quote"), store: &fakeStoreTransaction{}, verifyFunc: func([]byte) (attestation.Report, error) { return attestation.Report{}, assert.AnError @@ -734,6 +754,7 @@ func TestSignQuote(t *testing.T) { wantQuoteVerifyErr: true, }, "retrieving root key fails": { + quote: []byte("quote"), store: &fakeStoreTransaction{ getErr: assert.AnError, }, @@ -763,8 +784,7 @@ func TestSignQuote(t *testing.T) { require.NoError(err) require.NoError(wrapper.PutPrivateKey(constants.SKCoordinatorRootKey, rootKey)) - quote := []byte("quote") - signature, tcbStatus, err := api.verifyAndSignQuote(context.Background(), quote, tc.verifyFunc) + signature, tcbStatus, err := api.verifyAndSignQuote(context.Background(), tc.quote, tc.verifyFunc) if tc.wantErr { assert.Error(err) @@ -775,7 +795,7 @@ func TestSignQuote(t *testing.T) { return } assert.NoError(err) - hash := sha256.Sum256([]byte(base64.StdEncoding.EncodeToString(quote) + tcbStatus)) + hash := sha256.Sum256([]byte(base64.StdEncoding.EncodeToString(tc.quote) + tcbStatus)) assert.True(ecdsa.VerifyASN1(&rootKey.PublicKey, hash[:], signature)) }) }