handle.go 5.05 KB
Newer Older
1
2
3
4
5
6
7
8
package backend

import (
	"github.com/mhe/gabi"
	"github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/irmaserver"
)

Sietse Ringers's avatar
Sietse Ringers committed
9
10
11
12
13
// This file contains the handler functions for the protocol messages, receiving and returning normally
// Go-typed messages here (JSON (un)marshalling is handled by the router).
// Maintaining the session state is done here, as well as checking whether the session is in the
// appropriate status before handling the request.

14
15
var conf *irmaserver.Configuration

16
func (session *session) handleDelete() {
17
	if session.finished() {
18
		return
19
	}
20
	session.markAlive()
Sietse Ringers's avatar
Sietse Ringers committed
21

22
23
	// TODO const ProofStatusCancelled = irma.ProofStatus("CANCELLED") ?
	session.result = &irmaserver.SessionResult{Token: session.token}
24
	session.setStatus(irmaserver.StatusCancelled)
25
26
}

27
func (session *session) handleGetRequest(min, max *irma.ProtocolVersion) (irma.SessionRequest, *irma.RemoteError) {
28
29
30
31
32
	if session.status != irmaserver.StatusInitialized {
		return nil, getError(irmaserver.ErrorUnexpectedRequest, "Session already started")
	}
	session.markAlive()

33
34
	var err error
	if session.version, err = chooseProtocolVersion(min, max); err != nil {
35
		return nil, session.fail(irmaserver.ErrorProtocolVersion, "")
36
37
	}
	session.request.SetVersion(session.version)
38
39

	session.setStatus(irmaserver.StatusConnected)
40
	return session.request, nil
41
42
}

43
44
45
46
func (session *session) handlePostSignature(signature *irma.SignedMessage) (*irma.ProofStatus, *irma.RemoteError) {
	if session.status != irmaserver.StatusConnected {
		return nil, getError(irmaserver.ErrorUnexpectedRequest, "Session not yet started or already finished")
	}
47
	session.markAlive()
48

49
50
51
	session.result.Signature = signature
	session.result.Disclosed, session.result.Status = signature.Verify(
		conf.IrmaConfiguration, session.request.(*irma.SignatureRequest))
52
53
	session.setStatus(irmaserver.StatusDone)
	return &session.result.Status, nil
54
}
55

56
57
58
59
func (session *session) handlePostProofs(proofs gabi.ProofList) (*irma.ProofStatus, *irma.RemoteError) {
	if session.status != irmaserver.StatusConnected {
		return nil, getError(irmaserver.ErrorUnexpectedRequest, "Session not yet started or already finished")
	}
60
	session.markAlive()
61

62
63
	session.result.Disclosed, session.result.Status = irma.ProofList(proofs).Verify(
		conf.IrmaConfiguration, session.request.(*irma.DisclosureRequest))
64
65
	session.setStatus(irmaserver.StatusDone)
	return &session.result.Status, nil
66
67
}

Sietse Ringers's avatar
Sietse Ringers committed
68
69
70
71
72
func (session *session) handlePostCommitments(commitments *gabi.IssueCommitmentMessage) ([]*gabi.IssueSignatureMessage, *irma.RemoteError) {
	if session.status != irmaserver.StatusConnected {
		return nil, getError(irmaserver.ErrorUnexpectedRequest, "Session not yet started or already finished")
	}
	session.markAlive()
73

Sietse Ringers's avatar
Sietse Ringers committed
74
75
76
77
78
	request := session.request.(*irma.IssuanceRequest)
	discloseCount := len(request.Disclose)
	if len(commitments.Proofs) != len(request.Credentials)+discloseCount {
		return nil, session.fail(irmaserver.ErrorAttributesMissing, "")
	}
79

Sietse Ringers's avatar
Sietse Ringers committed
80
81
82
83
84
85
86
87
88
89
90
	// Compute list of public keys against which to verify the received proofs
	disclosureproofs := irma.ProofList(commitments.Proofs[:discloseCount])
	pubkeys, err := disclosureproofs.ExtractPublicKeys(conf.IrmaConfiguration)
	if err != nil {
		return nil, session.fail(irmaserver.ErrorInvalidProofs, err.Error())
	}
	for _, cred := range request.Credentials {
		iss := cred.CredentialTypeID.IssuerIdentifier()
		pubkey, _ := conf.IrmaConfiguration.PublicKey(iss, cred.KeyCounter) // No error, already checked earlier
		pubkeys = append(pubkeys, pubkey)
	}
91

Sietse Ringers's avatar
Sietse Ringers committed
92
93
94
95
96
97
98
99
100
101
102
	// Verify and merge keyshare server proofs, if any
	for i, proof := range commitments.Proofs {
		pubkey := pubkeys[i]
		schemeid := irma.NewIssuerIdentifier(pubkey.Issuer).SchemeManagerIdentifier()
		if conf.IrmaConfiguration.SchemeManagers[schemeid].Distributed() {
			proofP, err := session.getProofP(commitments, schemeid)
			if err != nil {
				return nil, session.fail(irmaserver.ErrorKeyshareProofMissing, err.Error())
			}
			proof.MergeProofP(proofP, pubkey)
		}
103
104
	}

Sietse Ringers's avatar
Sietse Ringers committed
105
106
107
108
109
	// Verify all proofs and check disclosed attributes, if any, against request
	session.result.Disclosed, session.result.Status = irma.ProofList(commitments.Proofs).VerifyAgainstDisjunctions(
		conf.IrmaConfiguration, request.Disclose, request.Context, request.Nonce, pubkeys, false)
	if session.result.Status != irma.ProofStatusValid {
		return nil, session.fail(irmaserver.ErrorInvalidProofs, "")
110
	}
Sietse Ringers's avatar
Sietse Ringers committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

	// Compute CL signatures
	var sigs []*gabi.IssueSignatureMessage
	for i, cred := range request.Credentials {
		id := cred.CredentialTypeID.IssuerIdentifier()
		pk, _ := conf.IrmaConfiguration.PublicKey(id, cred.KeyCounter)
		issuer := gabi.NewIssuer(conf.PrivateKeys[id], pk, one)
		proof := commitments.Proofs[i+discloseCount].(*gabi.ProofU)
		attributes, err := cred.AttributeList(conf.IrmaConfiguration, 0x03)
		if err != nil {
			return nil, session.fail(irmaserver.ErrorUnknown, err.Error())
		}
		sig, err := issuer.IssueSignature(proof.U, attributes.Ints, commitments.Nonce2)
		if err != nil {
			return nil, session.fail(irmaserver.ErrorUnknown, err.Error())
		}
		sigs = append(sigs, sig)
128
	}
Sietse Ringers's avatar
Sietse Ringers committed
129
130
131

	session.setStatus(irmaserver.StatusDone)
	return sigs, nil
132
}