Skip to content

Commit

Permalink
verify nitro attestations were valid when written versus the current (#…
Browse files Browse the repository at this point in the history
…2140)

time
  • Loading branch information
evq authored Oct 14, 2023
1 parent 4a8f9ae commit 37c4be2
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 11 deletions.
2 changes: 1 addition & 1 deletion libs/httpsignature/nitro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestVerifyNitroAttestation(t *testing.T) {
t.Fatal("error reading sample attestation doc:", err)
}

verifier := NitroVerifier{PCRs: pcrs, now: now}
verifier := NitroVerifier{PCRs: pcrs, Now: now}

Check failure on line 33 in libs/httpsignature/nitro_test.go

View workflow job for this annotation

GitHub Actions / lint

unknown field `PCRs` in struct literal (typecheck)

valid, err := verifier.Verify([]byte{}, doc, crypto.Hash(0))
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions libs/nitro/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ func (s Signer) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (si
// Verifier specifies the PCR values required for verification
type Verifier struct {
PCRs map[uint][]byte
now func() time.Time
Now func() time.Time
}

// NewVerifier returns a new verifier for nitro attestations
func NewVerifier(pcrs map[uint][]byte) Verifier {
return Verifier{
PCRs: pcrs,
now: time.Now,
Now: time.Now,
}
}

Expand All @@ -136,7 +136,7 @@ func (v Verifier) verifySigOnlyNotPCRs(message, sig []byte, opts crypto.SignerOp
sig,
nitrite.VerifyOptions{
Roots: pool,
CurrentTime: v.now(),
CurrentTime: v.Now(),
},
)
if nil != err {
Expand Down
5 changes: 3 additions & 2 deletions libs/payments/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto"
"io"
"time"
)

// Signator is an interface for cryptographic signature creation
Expand All @@ -19,6 +20,6 @@ type Verifier interface {

// Keystore provides a way to lookup a public key based on the keyID a request was signed with
type Keystore interface {
// LookupVerifier based on the keyID
LookupVerifier(ctx context.Context, keyID string) (context.Context, *Verifier, error)
// LookupVerifier based on the keyID and updatedAt
LookupVerifier(ctx context.Context, keyID string, updatedAt time.Time) (context.Context, *Verifier, error)
}
4 changes: 3 additions & 1 deletion libs/payments/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/rand"
"encoding/json"
"fmt"
"time"

"github.com/google/uuid"
"github.com/shopspring/decimal"
Expand Down Expand Up @@ -50,6 +51,7 @@ type PaymentState struct {
Signature []byte `ion:"signature"`
PublicKey string `ion:"publicKey"`
ID uuid.UUID `ion:"idempotencyKey"`
UpdatedAt time.Time `ion:"-"`
}

// PaymentStateHistory is a sequence of payment states.
Expand Down Expand Up @@ -133,7 +135,7 @@ func (p PaymentStateHistory) GetAuthenticatedPaymentState(keystore Keystore, doc
// 3. the transition was valid
var authenticatedState AuthenticatedPaymentState
for i, state := range []PaymentState(p) {
_, verifier, err := keystore.LookupVerifier(context.Background(), state.PublicKey)
_, verifier, err := keystore.LookupVerifier(context.Background(), state.PublicKey, state.UpdatedAt)
if err != nil {
return nil, fmt.Errorf("signature validation for state with document ID %s failed: %w", documentID, err)
}
Expand Down
1 change: 1 addition & 0 deletions services/payments/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func (q *QLDBDatastore) GetPaymentStateHistory(ctx context.Context, documentID s
if err != nil {
return nil, fmt.Errorf("ion unmarshal failed: %w", err)
}
latestHistoryItem.Data.UpdatedAt = latestHistoryItem.Metadata.TxTime
stateHistory = append(stateHistory, latestHistoryItem.Data)
}

Expand Down
11 changes: 7 additions & 4 deletions services/payments/state_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"time"

"github.com/brave-intl/bat-go/libs/nitro"
"github.com/brave-intl/bat-go/libs/payments"
Expand All @@ -14,7 +15,7 @@ import (
var previousPCR2Values = []string{}

type VerifierStore struct {
verifiers map[string]payments.Verifier
verifiers map[string]nitro.Verifier
}

func NewVerifierStore() (*VerifierStore, error) {
Expand All @@ -23,7 +24,7 @@ func NewVerifierStore() (*VerifierStore, error) {
return nil, errors.New("could not retrieve nitro PCRs")
}

s := VerifierStore{verifiers: map[string]payments.Verifier{}}
s := VerifierStore{verifiers: map[string]nitro.Verifier{}}

// always accept attestations matching our own
pubKey := hex.EncodeToString(pcrs[2])
Expand All @@ -48,10 +49,12 @@ func NewVerifierStore() (*VerifierStore, error) {

}

func (s *VerifierStore) LookupVerifier(ctx context.Context, keyID string) (context.Context, *payments.Verifier, error) {
func (s *VerifierStore) LookupVerifier(ctx context.Context, keyID string, updatedAt time.Time) (context.Context, *payments.Verifier, error) {
for k, v := range s.verifiers {
if k == keyID {
return ctx, &v, nil
v.Now = func() time.Time { return updatedAt }
vv := (payments.Verifier)(v)
return ctx, &vv, nil
}
}
return ctx, nil, fmt.Errorf("unknown key: %s", keyID)
Expand Down

0 comments on commit 37c4be2

Please sign in to comment.