Skip to content

Commit

Permalink
fix: abort issuance or disclosure in server and client in case of exp…
Browse files Browse the repository at this point in the history
…ired public keys
  • Loading branch information
sietseringers committed Aug 5, 2020
1 parent 1e22953 commit 7641b40
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 5 deletions.
29 changes: 29 additions & 0 deletions internal/sessiontest/requestor_test.go
Expand Up @@ -436,3 +436,32 @@ func TestParallelSessions(t *testing.T) {
require.NoError(t, err)
require.Len(t, logs, 2)
}

func expireKey(t *testing.T, conf *irma.Configuration) {
pk, err := conf.PublicKey(irma.NewIssuerIdentifier("irma-demo.RU"), 2)
require.NoError(t, err)
pk.ExpiryDate = 1500000000
}

func TestIssueExpiredKey(t *testing.T) {
client, handler := parseStorage(t)
defer test.ClearTestStorage(t, handler.storage)
StartIrmaServer(t, false, "")
defer StopIrmaServer()

// issuance sessions using valid, nonexpired public keys work
result := requestorSessionHelper(t, getIssuanceRequest(true), client, sessionOptionReuseServer)
require.Nil(t, result.Err)
require.Equal(t, irma.ProofStatusValid, result.ProofStatus)

// client aborts issuance sessions in case of expired public keys
expireKey(t, client.Configuration)
result = requestorSessionHelper(t, getIssuanceRequest(true), client, sessionOptionReuseServer, sessionOptionIgnoreError)
require.Nil(t, result.Err)
require.Equal(t, server.StatusCancelled, result.Status)

// server aborts issuance sessions in case of expired public keys
expireKey(t, irmaServerConfiguration.IrmaConfiguration)
_, _, err := irmaServer.StartSession(getIssuanceRequest(true), nil)
require.Error(t, err)
}
20 changes: 20 additions & 0 deletions irmaclient/session.go
Expand Up @@ -278,6 +278,21 @@ func serverName(hostname string, request irma.SessionRequest, conf *irma.Configu
return sn
}

func checkKey(conf *irma.Configuration, issuer irma.IssuerIdentifier, counter uint) error {
id := fmt.Sprintf("%s-%d", issuer, counter)
pk, err := conf.PublicKey(issuer, counter)
if err != nil {
return err
}
if pk == nil {
return errors.Errorf("credential signed with unknown public key %s", id)
}
if time.Now().Unix() > pk.ExpiryDate {
return errors.Errorf("credential signed with expired key %s", id)
}
return nil
}

// processSessionInfo continues the session after all session state has been received:
// it checks if the session can be performed and asks the user for consent.
func (session *session) processSessionInfo() {
Expand Down Expand Up @@ -318,6 +333,11 @@ func (session *session) processSessionInfo() {
// Calculate singleton credentials to be removed
ir.RemovalCredentialInfoList = irma.CredentialInfoList{}
for _, credreq := range ir.Credentials {
err := checkKey(session.client.Configuration, credreq.CredentialTypeID.IssuerIdentifier(), credreq.KeyCounter)
if err != nil {
session.fail(&irma.SessionError{ErrorType: irma.ErrorInvalidRequest, Err: err})
return
}
preexistingCredentials := session.client.attrs(credreq.CredentialTypeID)
if len(preexistingCredentials) != 0 && preexistingCredentials[0].IsValid() && preexistingCredentials[0].CredentialType().IsSingleton {
ir.RemovalCredentialInfoList = append(ir.RemovalCredentialInfoList, preexistingCredentials[0].Info())
Expand Down
6 changes: 5 additions & 1 deletion server/irmaserver/helpers.go
Expand Up @@ -200,6 +200,10 @@ func (s *Server) validateIssuanceRequest(request *irma.IssuanceRequest) error {
if pubkey == nil {
return errors.Errorf("missing public key of issuer %s", iss.String())
}
now := time.Now()
if now.Unix() > pubkey.ExpiryDate {
return errors.Errorf("cannot issue using expired public key %s-%d", iss.String(), privatekey.Counter)
}
cred.KeyCounter = privatekey.Counter

if s.conf.IrmaConfiguration.CredentialTypes[cred.CredentialTypeID].RevocationSupported() {
Expand All @@ -222,7 +226,7 @@ func (s *Server) validateIssuanceRequest(request *irma.IssuanceRequest) error {
if cred.Validity == nil {
cred.Validity = &defaultValidity
}
if cred.Validity.Before(irma.Timestamp(time.Now())) {
if cred.Validity.Before(irma.Timestamp(now)) {
return errors.New("cannot issue expired credentials")
}
}
Expand Down
19 changes: 15 additions & 4 deletions verify.go
Expand Up @@ -74,7 +74,7 @@ func (pl ProofList) ExtractPublicKeys(configuration *Configuration) ([]*gabi.Pub

// Expired returns true if any of the contained disclosure proofs is specified at the specified time,
// or now, when the specified time is nil.
func (pl ProofList) Expired(configuration *Configuration, t *time.Time) bool {
func (pl ProofList) Expired(configuration *Configuration, t *time.Time) (bool, error) {
if t == nil {
temp := time.Now()
t = &temp
Expand All @@ -86,10 +86,17 @@ func (pl ProofList) Expired(configuration *Configuration, t *time.Time) bool {
}
metadata := MetadataFromInt(proofd.ADisclosed[1], configuration) // index 1 is metadata attribute
if metadata.Expiry().Before(*t) {
return true
return true, nil
}
pk, err := metadata.PublicKey()
if err != nil {
return false, err
}
if metadata.SigningDate().Unix() > pk.ExpiryDate {
return true, nil
}
}
return false
return false, nil
}

func extractAttribute(pl gabi.ProofList, index *DisclosedAttributeIndex, notrevoked *time.Time, conf *Configuration) (*DisclosedAttribute, *string, error) {
Expand Down Expand Up @@ -364,7 +371,11 @@ func (d *Disclosure) VerifyAgainstRequest(
}

// Check that all credentials were unexpired
if expired := ProofList(d.Proofs).Expired(configuration, validAt); expired {
expired, err := ProofList(d.Proofs).Expired(configuration, validAt)
if err != nil {
return nil, ProofStatusInvalid, err
}
if expired {
return list, ProofStatusExpired, nil
}

Expand Down

0 comments on commit 7641b40

Please sign in to comment.