Skip to content

Commit

Permalink
Merge pull request #12 from Amnesic-Systems/fail-debug-verification
Browse files Browse the repository at this point in the history
Fail verification if PCRs indicate debug mode.
  • Loading branch information
NullHypothesis authored Nov 2, 2024
2 parents 3c0d96e + 86413a9 commit 22570d6
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 6 deletions.
7 changes: 5 additions & 2 deletions cmd/veil/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,12 @@ func TestAttestation(t *testing.T) {
var a enclave.AttestationDoc
require.NoError(t, json.Unmarshal(body, &a))

// "Verify" the attestation document using our noop attester.
// Verify the attestation document. We expect no error but if the
// test is run inside a Nitro Enclave, we will get ErrDebugMode.
aux, err := attester.Verify(&a, c.nonce)
require.NoError(t, err, errFromBody(t, resp))
if err != nil {
require.ErrorIs(t, err, nitro.ErrDebugMode, errFromBody(t, resp))
}

// Ensure that the recovered nonce matches what we sent.
n, err := attestation.GetNonce(aux)
Expand Down
11 changes: 8 additions & 3 deletions internal/enclave/nitro/attester.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
)

var _ enclave.Attester = (*Attester)(nil)
var ErrDebugMode = errors.New("attestation document was produced in debug mode")

// Attester implements the attester interface by drawing on the AWS Nitro
// Enclave hypervisor.
Expand Down Expand Up @@ -102,8 +103,6 @@ func (a *Attester) Verify(
return nil, err
}

// TODO: return an error if the attestation mode was produced in debug mode.

// Verify that the attestation document contains the nonce that we may have
// asked it to embed.
if ourNonce != nil {
Expand All @@ -116,9 +115,15 @@ func (a *Attester) Verify(
}
}

// If the enclave is running in debug mode, return an error *and* the
// auxiliary information.
if res.Document.PCRs.FromDebugMode() {
err = ErrDebugMode
}

return &enclave.AuxInfo{
Nonce: convertFrom(res.Document.Nonce),
UserData: convertFrom(res.Document.UserData),
PublicKey: convertFrom(res.Document.PublicKey),
}, nil
}, err
}
13 changes: 13 additions & 0 deletions internal/enclave/nitro/pcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package nitro

import (
"bytes"
"crypto/sha512"

"github.com/Amnesic-Systems/veil/internal/enclave"
"github.com/Amnesic-Systems/veil/internal/errs"
)

var emptyPCR = make([]byte, sha512.Size384)

// pcr represents the enclave's platform configuration register (PCR) values.
type pcr map[uint][]byte

Expand All @@ -27,6 +30,16 @@ func getPCRs() (_ pcr, err error) {
return pcr(res.Document.PCRs), nil
}

// FromDebugMode returns true if the given PCR map was generated by an enclave
// in debug mode.
func (p pcr) FromDebugMode() bool {
// PCRs 0, 1, and 2 are set at compile time but will be unset if the enclave
// is running in debug mode.
return bytes.Equal(p[0], emptyPCR) &&
bytes.Equal(p[1], emptyPCR) &&
bytes.Equal(p[2], emptyPCR)
}

// Equal returns true if (and only if) the two given PCR maps are identical.
func (ours pcr) Equal(theirs pcr) bool {
// PCR4 contains a hash over the parent's instance ID. Our enclaves run
Expand Down
38 changes: 38 additions & 0 deletions internal/enclave/nitro/pcr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,44 @@ func TestGetPCRs(t *testing.T) {
require.Equal(t, pcrs1, pcrs2)
}

func TestPCRsFromDebugMode(t *testing.T) {
cases := []struct {
name string
pcrs pcr
want bool
}{
{
name: "empty",
pcrs: pcr{},
},
{
name: "debug mode",
pcrs: pcr{
0: emptyPCR,
1: emptyPCR,
2: emptyPCR,
3: []byte("foo"), // Should be ignored.
4: []byte("bar"), // Should be ignored.
},
want: true,
},
{
name: "not debug mode",
pcrs: pcr{
0: []byte("foo"),
1: emptyPCR,
2: emptyPCR,
},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
require.Equal(t, c.want, c.pcrs.FromDebugMode())
})
}
}

func TestPCRsEqual(t *testing.T) {
cases := []struct {
name string
Expand Down
6 changes: 5 additions & 1 deletion internal/service/attestation/aux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,12 @@ func TestBuilder(t *testing.T) {
doc, err := b.Attest(c.attestFields...)
require.NoError(t, err)

// Verify the attestation document. We expect no error but if the
// test is run inside a Nitro Enclave, we will get ErrDebugMode.
aux, err := attester.Verify(doc, nil)
require.NoError(t, err)
if err != nil {
require.ErrorIs(t, err, nitro.ErrDebugMode)
}
require.Equal(t, c.wantAux, aux)
})
}
Expand Down

0 comments on commit 22570d6

Please sign in to comment.