internal/provision/auth_test.go
raw ยท 3021 bytes
package provision
import (
"bytes"
"encoding/hex"
"testing"
)
func TestAuthenticationPersistenceAndRevocation(t *testing.T) {
s, dir, iid := paired(t)
if _, e := s.Handle(readerAdd()); e != nil {
t.Fatal(e)
}
if _, e := s.Handle(endpointAdd(iid)); e != nil {
t.Fatal(e)
}
c := s.AuthenticationCredentials()
var eid, pub string
for id, ep := range c.Issuers[iid].Endpoints {
eid = id
pub = ep.PublicKey
}
key := bytes.Repeat([]byte{7}, 32)
if e := s.SaveAuthenticatedKey(c, iid, eid, pub, key); e != nil {
t.Fatal(e)
}
restored, e := Open(dir)
if e != nil {
t.Fatal(e)
}
if restored.AuthenticationCredentials().Issuers[iid].Endpoints[eid].PersistentKey == "" {
t.Fatal("persistent key lost")
}
// Mutating a snapshot must never modify the live credential store.
delete(c.Issuers, iid)
c = s.AuthenticationCredentials()
calls := 0
if e := s.WithAuthorization(c, iid, eid, pub, func() error { calls++; return nil }); e != nil {
t.Fatal(e)
}
if e := s.Delete("controller.pairing"); e != nil {
t.Fatal(e)
}
if e := s.SaveAuthenticatedKey(c, iid, eid, pub, key); e == nil {
t.Fatal("revoked credential persisted")
}
if e := s.WithAuthorization(c, iid, eid, pub, func() error { calls++; return nil }); e == nil {
t.Fatal("revoked credential unlocked")
}
if calls != 1 {
t.Fatal("callback ran after revocation")
}
}
func TestAuthenticationRejectsReaderChangeAndInactive(t *testing.T) {
for _, mode := range []string{"reader", "inactive"} {
t.Run(mode, func(t *testing.T) {
s, _, iid := paired(t)
s.Handle(readerAdd())
s.Handle(endpointAdd(iid))
c := s.AuthenticationCredentials()
var eid, pub string
for id, ep := range c.Issuers[iid].Endpoints {
eid = id
pub = ep.PublicKey
}
e := s.update(func(d *Data) error {
if mode == "reader" {
d.HomeKey.ReaderIdentifier = "0908070605040302"
} else {
i := d.HomeKey.Issuers[iid]
ep := i.Endpoints[eid]
ep.KeyState = 0
i.Endpoints[eid] = ep
d.HomeKey.Issuers[iid] = i
}
return nil
})
if e != nil {
t.Fatal(e)
}
if e = s.WithAuthorization(c, iid, eid, pub, func() error { t.Fatal("unauthorized callback"); return nil }); e == nil {
t.Fatal("changed credentials accepted")
}
})
}
}
func TestReaderGroupIdentifier(t *testing.T) {
s, _, _ := paired(t)
if s.ReaderGroupIdentifier() != nil {
t.Fatal("unprovisioned reader has ECP group")
}
if _, err := s.Handle(readerAdd()); err != nil {
t.Fatal(err)
}
// Independent SHA256("key-identifier" || scalar=1) vector.
want := mustHex("539a3f91ed603fef")
group := s.ReaderGroupIdentifier()
if !bytes.Equal(group, want) {
t.Fatalf("wrong group: %s", hex.EncodeToString(group))
}
group[0] ^= 1
if !bytes.Equal(s.ReaderGroupIdentifier(), want) {
t.Fatal("group snapshot aliases store")
}
if _, err := s.Handle(request(3, 6, TLV(4, want))); err != nil {
t.Fatal(err)
}
if s.ReaderGroupIdentifier() != nil {
t.Fatal("removed reader still has ECP group")
}
}