1package otr3
2
3import (
4	"crypto/hmac"
5	"crypto/subtle"
6	"io"
7	"math/big"
8	"time"
9)
10
11var dontIgnoreFastRepeatQueryMessage = "false"
12
13type ake struct {
14	secretExponent   *big.Int
15	ourPublicValue   *big.Int
16	theirPublicValue *big.Int
17
18	// TODO: why this number here?
19	r [16]byte
20
21	encryptedGx []byte
22
23	// SIZE: this should always be version.hash2Length
24	xhashedGx []byte
25
26	revealKey akeKeys
27	sigKey    akeKeys
28
29	state authState
30	keys  keyManagementContext
31
32	lastStateChange time.Time
33}
34
35func (c *Conversation) ensureAKE() {
36	if c.ake != nil {
37		return
38	}
39
40	c.initAKE()
41}
42
43func (c *Conversation) initAKE() {
44	c.ake = &ake{
45		state: authStateNone{},
46	}
47}
48
49func (c *Conversation) calcAKEKeys(s *big.Int) {
50	c.ssid, c.ake.revealKey, c.ake.sigKey = calculateAKEKeys(s, c.version)
51}
52
53func (c *Conversation) setSecretExponent(val *big.Int) {
54	c.ake.secretExponent = new(big.Int).Set(val)
55	c.ake.ourPublicValue = modExp(g1, val)
56}
57
58func (c *Conversation) calcDHSharedSecret() *big.Int {
59	return modExp(c.ake.theirPublicValue, c.ake.secretExponent)
60}
61
62func (c *Conversation) generateEncryptedSignature(key *akeKeys) ([]byte, error) {
63	verifyData := appendAll(c.ake.ourPublicValue, c.ake.theirPublicValue, c.ourCurrentKey.PublicKey(), c.ake.keys.ourKeyID)
64
65	mb := sumHMAC(key.m1, verifyData, c.version)
66	xb, err := c.calcXb(key, mb)
67
68	if err != nil {
69		return nil, err
70	}
71
72	return appendData(nil, xb), nil
73}
74func appendAll(one, two *big.Int, publicKey PublicKey, keyID uint32) []byte {
75	return appendWord(append(appendMPI(appendMPI(nil, one), two), publicKey.serialize()...), keyID)
76}
77
78func fixedSize(s int, v []byte) []byte {
79	if len(v) < s {
80		vv := make([]byte, s)
81		copy(vv, v)
82		return vv
83	}
84	return v
85}
86
87func (c *Conversation) calcXb(key *akeKeys, mb []byte) ([]byte, error) {
88	xb := c.ourCurrentKey.PublicKey().serialize()
89	xb = appendWord(xb, c.ake.keys.ourKeyID)
90
91	sigb, err := c.ourCurrentKey.Sign(c.rand(), mb)
92	if err == io.ErrUnexpectedEOF {
93		return nil, errShortRandomRead
94	}
95
96	if err != nil {
97		return nil, err
98	}
99
100	// this error can't happen, since key.c is fixed to the correct size
101	xb, _ = encrypt(fixedSize(c.version.keyLength(), key.c), append(xb, sigb...))
102
103	return xb, nil
104}
105
106// dhCommitMessage = bob = x
107// Bob ---- DH Commit -----------> Alice
108func (c *Conversation) dhCommitMessage() ([]byte, error) {
109	c.initAKE()
110	c.ake.keys.ourKeyID = 0
111
112	// TODO: where does this 40 come from?
113	x, err := c.randMPI(make([]byte, 40))
114	if err != nil {
115		return nil, err
116	}
117
118	c.setSecretExponent(x)
119	wipeBigInt(x)
120
121	if err := c.randomInto(c.ake.r[:]); err != nil {
122		return nil, err
123	}
124
125	// this can't return an error, since ake.r is of a fixed size that is always correct
126	c.ake.encryptedGx, _ = encrypt(c.ake.r[:], appendMPI(nil, c.ake.ourPublicValue))
127
128	return c.serializeDHCommit(c.ake.ourPublicValue), nil
129}
130
131func (c *Conversation) serializeDHCommit(public *big.Int) []byte {
132	dhCommitMsg := dhCommit{
133		encryptedGx: c.ake.encryptedGx,
134		yhashedGx:   c.version.hash2(appendMPI(nil, public)),
135	}
136	return dhCommitMsg.serialize()
137}
138
139// dhKeyMessage = alice = y
140// Alice -- DH Key --------------> Bob
141func (c *Conversation) dhKeyMessage() ([]byte, error) {
142	c.initAKE()
143
144	// TODO: where does this 40 come from?
145	y, err := c.randMPI(make([]byte, 40)[:])
146
147	if err != nil {
148		return nil, err
149	}
150
151	c.setSecretExponent(y)
152	wipeBigInt(y)
153
154	return c.serializeDHKey(), nil
155}
156
157func (c *Conversation) serializeDHKey() []byte {
158	dhKeyMsg := dhKey{
159		gy: c.ake.ourPublicValue,
160	}
161
162	return dhKeyMsg.serialize()
163}
164
165// revealSigMessage = bob = x
166// Bob ---- Reveal Signature ----> Alice
167func (c *Conversation) revealSigMessage() ([]byte, error) {
168	c.calcAKEKeys(c.calcDHSharedSecret())
169	c.ake.keys.ourKeyID++
170
171	encryptedSig, err := c.generateEncryptedSignature(&c.ake.revealKey)
172	if err != nil {
173		return nil, err
174	}
175
176	macSig := sumHMAC(c.ake.revealKey.m2, encryptedSig, c.version)
177	revealSigMsg := revealSig{
178		r:            c.ake.r,
179		encryptedSig: encryptedSig,
180		macSig:       macSig,
181	}
182
183	return revealSigMsg.serialize(c.version), nil
184}
185
186// sigMessage = alice = y
187// Alice -- Signature -----------> Bob
188func (c *Conversation) sigMessage() ([]byte, error) {
189	c.ake.keys.ourKeyID++
190
191	encryptedSig, err := c.generateEncryptedSignature(&c.ake.sigKey)
192	if err != nil {
193		return nil, err
194	}
195
196	macSig := sumHMAC(c.ake.sigKey.m2, encryptedSig, c.version)
197	sigMsg := sig{
198		encryptedSig: encryptedSig,
199		macSig:       macSig,
200	}
201
202	return sigMsg.serialize(c.version), nil
203}
204
205// processDHCommit = alice = y
206// Bob ---- DH Commit -----------> Alice
207func (c *Conversation) processDHCommit(msg []byte) error {
208	dhCommitMsg := dhCommit{}
209	err := dhCommitMsg.deserialize(msg)
210	if err != nil {
211		return err
212	}
213
214	c.ake.encryptedGx = dhCommitMsg.encryptedGx
215	c.ake.xhashedGx = dhCommitMsg.yhashedGx
216
217	return err
218}
219
220// processDHKey = bob = x
221// Alice -- DH Key --------------> Bob
222func (c *Conversation) processDHKey(msg []byte) (isSame bool, err error) {
223	dhKeyMsg := dhKey{}
224	err = dhKeyMsg.deserialize(msg)
225	if err != nil {
226		return false, err
227	}
228
229	if !isGroupElement(dhKeyMsg.gy) {
230		return false, newOtrError("DH value out of range")
231	}
232
233	//If receive same public key twice, just retransmit the previous Reveal Signature
234	if c.ake.theirPublicValue != nil {
235		isSame = eq(c.ake.theirPublicValue, dhKeyMsg.gy)
236		return
237	}
238
239	c.ake.theirPublicValue = dhKeyMsg.gy
240	return
241}
242
243// processRevealSig = alice = y
244// Bob ---- Reveal Signature ----> Alice
245func (c *Conversation) processRevealSig(msg []byte) (err error) {
246	revealSigMsg := revealSig{}
247	err = revealSigMsg.deserialize(msg, c.version)
248	if err != nil {
249		return
250	}
251
252	r := revealSigMsg.r[:]
253	theirMAC := revealSigMsg.macSig
254	encryptedSig := revealSigMsg.encryptedSig
255
256	decryptedGx := make([]byte, len(c.ake.encryptedGx))
257	if err = decrypt(r, decryptedGx, c.ake.encryptedGx); err != nil {
258		return
259	}
260
261	if err = checkDecryptedGx(decryptedGx, c.ake.xhashedGx, c.version); err != nil {
262		return
263	}
264
265	if c.ake.theirPublicValue, err = extractGx(decryptedGx); err != nil {
266		return
267	}
268
269	c.calcAKEKeys(c.calcDHSharedSecret())
270	if err = c.processEncryptedSig(encryptedSig, theirMAC, &c.ake.revealKey); err != nil {
271		return newOtrError("in reveal signature message: " + err.Error())
272	}
273
274	return nil
275}
276
277// processSig = bob = x
278// Alice -- Signature -----------> Bob
279func (c *Conversation) processSig(msg []byte) (err error) {
280	sigMsg := sig{}
281	err = sigMsg.deserialize(msg)
282	if err != nil {
283		return
284	}
285
286	theirMAC := sigMsg.macSig
287	encryptedSig := sigMsg.encryptedSig
288
289	if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.ake.sigKey); err != nil {
290		return newOtrError("in signature message: " + err.Error())
291	}
292
293	return nil
294}
295
296func (c *Conversation) checkedSignatureVerification(mb, sig []byte) error {
297	rest, ok := c.theirKey.Verify(mb, sig)
298	if !ok {
299		return newOtrError("bad signature in encrypted signature")
300	}
301
302	if len(rest) > 0 {
303		return errCorruptEncryptedSignature
304	}
305
306	return nil
307}
308
309func verifyEncryptedSignatureMAC(encryptedSig []byte, theirMAC []byte, keys *akeKeys, v otrVersion) error {
310	tomac := appendData(nil, encryptedSig)
311
312	myMAC := sumHMAC(keys.m2, tomac, v)[:v.truncateLength()]
313
314	if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
315		return newOtrError("bad signature MAC in encrypted signature")
316	}
317
318	return nil
319}
320
321func (c *Conversation) parseTheirKey(key []byte) (sig []byte, keyID uint32, err error) {
322	var rest []byte
323	var ok1 bool
324	rest, ok1, c.theirKey = ParsePublicKey(key)
325	sig, keyID, ok2 := extractWord(rest)
326
327	if !ok1 || !ok2 {
328		return nil, 0, errCorruptEncryptedSignature
329	}
330
331	return
332}
333
334func (c *Conversation) expectedMessageHMAC(keyID uint32, keys *akeKeys) []byte {
335	verifyData := appendAll(c.ake.theirPublicValue, c.ake.ourPublicValue, c.theirKey, keyID)
336	return sumHMAC(keys.m1, verifyData, c.version)
337}
338
339func (c *Conversation) processEncryptedSig(encryptedSig []byte, theirMAC []byte, keys *akeKeys) error {
340	if err := verifyEncryptedSignatureMAC(encryptedSig, theirMAC, keys, c.version); err != nil {
341		return err
342	}
343
344	decryptedSig := encryptedSig
345	if err := decrypt(fixedSize(c.version.keyLength(), keys.c), decryptedSig, encryptedSig); err != nil {
346		return err
347	}
348
349	sig, keyID, err := c.parseTheirKey(decryptedSig)
350	if err != nil {
351		return err
352	}
353
354	mb := c.expectedMessageHMAC(keyID, keys)
355	if err := c.checkedSignatureVerification(mb, sig); err != nil {
356		return err
357	}
358
359	c.ake.keys.theirKeyID = keyID
360
361	return nil
362}
363
364func extractGx(decryptedGx []byte) (*big.Int, error) {
365	newData, gx, ok := extractMPI(decryptedGx)
366	if !ok || len(newData) > 0 {
367		return gx, newOtrError("gx corrupt after decryption")
368	}
369
370	if !isGroupElement(gx) {
371		return gx, newOtrError("DH value out of range")
372	}
373
374	return gx, nil
375}
376
377func sumHMAC(key, data []byte, v otrVersion) []byte {
378	mac := hmac.New(v.hash2Instance, key)
379	mac.Write(data)
380	return mac.Sum(nil)
381}
382
383func checkDecryptedGx(decryptedGx, hashedGx []byte, v otrVersion) error {
384	digest := v.hash2(decryptedGx)
385
386	if subtle.ConstantTimeCompare(digest[:], hashedGx[:]) == 0 {
387		return newOtrError("bad commit MAC in reveal signature message")
388	}
389
390	return nil
391}
392