1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package otr implements the Off The Record protocol as specified in
6// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
7package otr // import "golang.org/x/crypto/otr"
8
9import (
10	"bytes"
11	"crypto/aes"
12	"crypto/cipher"
13	"crypto/dsa"
14	"crypto/hmac"
15	"crypto/rand"
16	"crypto/sha1"
17	"crypto/sha256"
18	"crypto/subtle"
19	"encoding/base64"
20	"encoding/hex"
21	"errors"
22	"hash"
23	"io"
24	"math/big"
25	"strconv"
26)
27
28// SecurityChange describes a change in the security state of a Conversation.
29type SecurityChange int
30
31const (
32	NoChange SecurityChange = iota
33	// NewKeys indicates that a key exchange has completed. This occurs
34	// when a conversation first becomes encrypted, and when the keys are
35	// renegotiated within an encrypted conversation.
36	NewKeys
37	// SMPSecretNeeded indicates that the peer has started an
38	// authentication and that we need to supply a secret. Call SMPQuestion
39	// to get the optional, human readable challenge and then Authenticate
40	// to supply the matching secret.
41	SMPSecretNeeded
42	// SMPComplete indicates that an authentication completed. The identity
43	// of the peer has now been confirmed.
44	SMPComplete
45	// SMPFailed indicates that an authentication failed.
46	SMPFailed
47	// ConversationEnded indicates that the peer ended the secure
48	// conversation.
49	ConversationEnded
50)
51
52// QueryMessage can be sent to a peer to start an OTR conversation.
53var QueryMessage = "?OTRv2?"
54
55// ErrorPrefix can be used to make an OTR error by appending an error message
56// to it.
57var ErrorPrefix = "?OTR Error:"
58
59var (
60	fragmentPartSeparator = []byte(",")
61	fragmentPrefix        = []byte("?OTR,")
62	msgPrefix             = []byte("?OTR:")
63	queryMarker           = []byte("?OTR")
64)
65
66// isQuery attempts to parse an OTR query from msg and returns the greatest
67// common version, or 0 if msg is not an OTR query.
68func isQuery(msg []byte) (greatestCommonVersion int) {
69	pos := bytes.Index(msg, queryMarker)
70	if pos == -1 {
71		return 0
72	}
73	for i, c := range msg[pos+len(queryMarker):] {
74		if i == 0 {
75			if c == '?' {
76				// Indicates support for version 1, but we don't
77				// implement that.
78				continue
79			}
80
81			if c != 'v' {
82				// Invalid message
83				return 0
84			}
85
86			continue
87		}
88
89		if c == '?' {
90			// End of message
91			return
92		}
93
94		if c == ' ' || c == '\t' {
95			// Probably an invalid message
96			return 0
97		}
98
99		if c == '2' {
100			greatestCommonVersion = 2
101		}
102	}
103
104	return 0
105}
106
107const (
108	statePlaintext = iota
109	stateEncrypted
110	stateFinished
111)
112
113const (
114	authStateNone = iota
115	authStateAwaitingDHKey
116	authStateAwaitingRevealSig
117	authStateAwaitingSig
118)
119
120const (
121	msgTypeDHCommit  = 2
122	msgTypeData      = 3
123	msgTypeDHKey     = 10
124	msgTypeRevealSig = 17
125	msgTypeSig       = 18
126)
127
128const (
129	// If the requested fragment size is less than this, it will be ignored.
130	minFragmentSize = 18
131	// Messages are padded to a multiple of this number of bytes.
132	paddingGranularity = 256
133	// The number of bytes in a Diffie-Hellman private value (320-bits).
134	dhPrivateBytes = 40
135	// The number of bytes needed to represent an element of the DSA
136	// subgroup (160-bits).
137	dsaSubgroupBytes = 20
138	// The number of bytes of the MAC that are sent on the wire (160-bits).
139	macPrefixBytes = 20
140)
141
142// These are the global, common group parameters for OTR.
143var (
144	p       *big.Int // group prime
145	g       *big.Int // group generator
146	q       *big.Int // group order
147	pMinus2 *big.Int
148)
149
150func init() {
151	p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16)
152	q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16)
153	g = new(big.Int).SetInt64(2)
154	pMinus2 = new(big.Int).Sub(p, g)
155}
156
157// Conversation represents a relation with a peer. The zero value is a valid
158// Conversation, although PrivateKey must be set.
159//
160// When communicating with a peer, all inbound messages should be passed to
161// Conversation.Receive and all outbound messages to Conversation.Send. The
162// Conversation will take care of maintaining the encryption state and
163// negotiating encryption as needed.
164type Conversation struct {
165	// PrivateKey contains the private key to use to sign key exchanges.
166	PrivateKey *PrivateKey
167
168	// Rand can be set to override the entropy source. Otherwise,
169	// crypto/rand will be used.
170	Rand io.Reader
171	// If FragmentSize is set, all messages produced by Receive and Send
172	// will be fragmented into messages of, at most, this number of bytes.
173	FragmentSize int
174
175	// Once Receive has returned NewKeys once, the following fields are
176	// valid.
177	SSID           [8]byte
178	TheirPublicKey PublicKey
179
180	state, authState int
181
182	r       [16]byte
183	x, y    *big.Int
184	gx, gy  *big.Int
185	gxBytes []byte
186	digest  [sha256.Size]byte
187
188	revealKeys, sigKeys akeKeys
189
190	myKeyId         uint32
191	myCurrentDHPub  *big.Int
192	myCurrentDHPriv *big.Int
193	myLastDHPub     *big.Int
194	myLastDHPriv    *big.Int
195
196	theirKeyId        uint32
197	theirCurrentDHPub *big.Int
198	theirLastDHPub    *big.Int
199
200	keySlots [4]keySlot
201
202	myCounter    [8]byte
203	theirLastCtr [8]byte
204	oldMACs      []byte
205
206	k, n int // fragment state
207	frag []byte
208
209	smp smpState
210}
211
212// A keySlot contains key material for a specific (their keyid, my keyid) pair.
213type keySlot struct {
214	// used is true if this slot is valid. If false, it's free for reuse.
215	used                   bool
216	theirKeyId             uint32
217	myKeyId                uint32
218	sendAESKey, recvAESKey []byte
219	sendMACKey, recvMACKey []byte
220	theirLastCtr           [8]byte
221}
222
223// akeKeys are generated during key exchange. There's one set for the reveal
224// signature message and another for the signature message. In the protocol
225// spec the latter are indicated with a prime mark.
226type akeKeys struct {
227	c      [16]byte
228	m1, m2 [32]byte
229}
230
231func (c *Conversation) rand() io.Reader {
232	if c.Rand != nil {
233		return c.Rand
234	}
235	return rand.Reader
236}
237
238func (c *Conversation) randMPI(buf []byte) *big.Int {
239	_, err := io.ReadFull(c.rand(), buf)
240	if err != nil {
241		panic("otr: short read from random source")
242	}
243
244	return new(big.Int).SetBytes(buf)
245}
246
247// tlv represents the type-length value from the protocol.
248type tlv struct {
249	typ, length uint16
250	data        []byte
251}
252
253const (
254	tlvTypePadding          = 0
255	tlvTypeDisconnected     = 1
256	tlvTypeSMP1             = 2
257	tlvTypeSMP2             = 3
258	tlvTypeSMP3             = 4
259	tlvTypeSMP4             = 5
260	tlvTypeSMPAbort         = 6
261	tlvTypeSMP1WithQuestion = 7
262)
263
264// Receive handles a message from a peer. It returns a human readable message,
265// an indicator of whether that message was encrypted, a hint about the
266// encryption state and zero or more messages to send back to the peer.
267// These messages do not need to be passed to Send before transmission.
268func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) {
269	if bytes.HasPrefix(in, fragmentPrefix) {
270		in, err = c.processFragment(in)
271		if in == nil || err != nil {
272			return
273		}
274	}
275
276	if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' {
277		in = in[len(msgPrefix) : len(in)-1]
278	} else if version := isQuery(in); version > 0 {
279		c.authState = authStateAwaitingDHKey
280		c.reset()
281		toSend = c.encode(c.generateDHCommit())
282		return
283	} else {
284		// plaintext message
285		out = in
286		return
287	}
288
289	msg := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
290	msgLen, err := base64.StdEncoding.Decode(msg, in)
291	if err != nil {
292		err = errors.New("otr: invalid base64 encoding in message")
293		return
294	}
295	msg = msg[:msgLen]
296
297	// The first two bytes are the protocol version (2)
298	if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 {
299		err = errors.New("otr: invalid OTR message")
300		return
301	}
302
303	msgType := int(msg[2])
304	msg = msg[3:]
305
306	switch msgType {
307	case msgTypeDHCommit:
308		switch c.authState {
309		case authStateNone:
310			c.authState = authStateAwaitingRevealSig
311			if err = c.processDHCommit(msg); err != nil {
312				return
313			}
314			c.reset()
315			toSend = c.encode(c.generateDHKey())
316			return
317		case authStateAwaitingDHKey:
318			// This is a 'SYN-crossing'. The greater digest wins.
319			var cmp int
320			if cmp, err = c.compareToDHCommit(msg); err != nil {
321				return
322			}
323			if cmp > 0 {
324				// We win. Retransmit DH commit.
325				toSend = c.encode(c.serializeDHCommit())
326				return
327			} else {
328				// They win. We forget about our DH commit.
329				c.authState = authStateAwaitingRevealSig
330				if err = c.processDHCommit(msg); err != nil {
331					return
332				}
333				c.reset()
334				toSend = c.encode(c.generateDHKey())
335				return
336			}
337		case authStateAwaitingRevealSig:
338			if err = c.processDHCommit(msg); err != nil {
339				return
340			}
341			toSend = c.encode(c.serializeDHKey())
342		case authStateAwaitingSig:
343			if err = c.processDHCommit(msg); err != nil {
344				return
345			}
346			c.reset()
347			toSend = c.encode(c.generateDHKey())
348			c.authState = authStateAwaitingRevealSig
349		default:
350			panic("bad state")
351		}
352	case msgTypeDHKey:
353		switch c.authState {
354		case authStateAwaitingDHKey:
355			var isSame bool
356			if isSame, err = c.processDHKey(msg); err != nil {
357				return
358			}
359			if isSame {
360				err = errors.New("otr: unexpected duplicate DH key")
361				return
362			}
363			toSend = c.encode(c.generateRevealSig())
364			c.authState = authStateAwaitingSig
365		case authStateAwaitingSig:
366			var isSame bool
367			if isSame, err = c.processDHKey(msg); err != nil {
368				return
369			}
370			if isSame {
371				toSend = c.encode(c.serializeDHKey())
372			}
373		}
374	case msgTypeRevealSig:
375		if c.authState != authStateAwaitingRevealSig {
376			return
377		}
378		if err = c.processRevealSig(msg); err != nil {
379			return
380		}
381		toSend = c.encode(c.generateSig())
382		c.authState = authStateNone
383		c.state = stateEncrypted
384		change = NewKeys
385	case msgTypeSig:
386		if c.authState != authStateAwaitingSig {
387			return
388		}
389		if err = c.processSig(msg); err != nil {
390			return
391		}
392		c.authState = authStateNone
393		c.state = stateEncrypted
394		change = NewKeys
395	case msgTypeData:
396		if c.state != stateEncrypted {
397			err = errors.New("otr: encrypted message received without encrypted session established")
398			return
399		}
400		var tlvs []tlv
401		out, tlvs, err = c.processData(msg)
402		encrypted = true
403
404	EachTLV:
405		for _, inTLV := range tlvs {
406			switch inTLV.typ {
407			case tlvTypeDisconnected:
408				change = ConversationEnded
409				c.state = stateFinished
410				break EachTLV
411			case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion:
412				var reply tlv
413				var complete bool
414				reply, complete, err = c.processSMP(inTLV)
415				if err == smpSecretMissingError {
416					err = nil
417					change = SMPSecretNeeded
418					c.smp.saved = &inTLV
419					return
420				}
421				if err == smpFailureError {
422					err = nil
423					change = SMPFailed
424				} else if complete {
425					change = SMPComplete
426				}
427				if reply.typ != 0 {
428					toSend = c.encode(c.generateData(nil, &reply))
429				}
430				break EachTLV
431			default:
432				// skip unknown TLVs
433			}
434		}
435	default:
436		err = errors.New("otr: unknown message type " + strconv.Itoa(msgType))
437	}
438
439	return
440}
441
442// Send takes a human readable message from the local user, possibly encrypts
443// it and returns zero one or more messages to send to the peer.
444func (c *Conversation) Send(msg []byte) ([][]byte, error) {
445	switch c.state {
446	case statePlaintext:
447		return [][]byte{msg}, nil
448	case stateEncrypted:
449		return c.encode(c.generateData(msg, nil)), nil
450	case stateFinished:
451		return nil, errors.New("otr: cannot send message because secure conversation has finished")
452	}
453
454	return nil, errors.New("otr: cannot send message in current state")
455}
456
457// SMPQuestion returns the human readable challenge question from the peer.
458// It's only valid after Receive has returned SMPSecretNeeded.
459func (c *Conversation) SMPQuestion() string {
460	return c.smp.question
461}
462
463// Authenticate begins an authentication with the peer. Authentication involves
464// an optional challenge message and a shared secret. The authentication
465// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which
466// indicates that a new authentication is happening and thus this one was
467// aborted) or SMPFailed.
468func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) {
469	if c.state != stateEncrypted {
470		err = errors.New("otr: can't authenticate a peer without a secure conversation established")
471		return
472	}
473
474	if c.smp.saved != nil {
475		c.calcSMPSecret(mutualSecret, false /* they started it */)
476
477		var out tlv
478		var complete bool
479		out, complete, err = c.processSMP(*c.smp.saved)
480		if complete {
481			panic("SMP completed on the first message")
482		}
483		c.smp.saved = nil
484		if out.typ != 0 {
485			toSend = c.encode(c.generateData(nil, &out))
486		}
487		return
488	}
489
490	c.calcSMPSecret(mutualSecret, true /* we started it */)
491	outs := c.startSMP(question)
492	for _, out := range outs {
493		toSend = append(toSend, c.encode(c.generateData(nil, &out))...)
494	}
495	return
496}
497
498// End ends a secure conversation by generating a termination message for
499// the peer and switches to unencrypted communication.
500func (c *Conversation) End() (toSend [][]byte) {
501	switch c.state {
502	case statePlaintext:
503		return nil
504	case stateEncrypted:
505		c.state = statePlaintext
506		return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected}))
507	case stateFinished:
508		c.state = statePlaintext
509		return nil
510	}
511	panic("unreachable")
512}
513
514// IsEncrypted returns true if a message passed to Send would be encrypted
515// before transmission. This result remains valid until the next call to
516// Receive or End, which may change the state of the Conversation.
517func (c *Conversation) IsEncrypted() bool {
518	return c.state == stateEncrypted
519}
520
521var fragmentError = errors.New("otr: invalid OTR fragment")
522
523// processFragment processes a fragmented OTR message and possibly returns a
524// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is
525// the fragment number (starting from 1), n is the number of fragments in this
526// message and msg is a substring of the base64 encoded message.
527func (c *Conversation) processFragment(in []byte) (out []byte, err error) {
528	in = in[len(fragmentPrefix):] // remove "?OTR,"
529	parts := bytes.Split(in, fragmentPartSeparator)
530	if len(parts) != 4 || len(parts[3]) != 0 {
531		return nil, fragmentError
532	}
533
534	k, err := strconv.Atoi(string(parts[0]))
535	if err != nil {
536		return nil, fragmentError
537	}
538
539	n, err := strconv.Atoi(string(parts[1]))
540	if err != nil {
541		return nil, fragmentError
542	}
543
544	if k < 1 || n < 1 || k > n {
545		return nil, fragmentError
546	}
547
548	if k == 1 {
549		c.frag = append(c.frag[:0], parts[2]...)
550		c.k, c.n = k, n
551	} else if n == c.n && k == c.k+1 {
552		c.frag = append(c.frag, parts[2]...)
553		c.k++
554	} else {
555		c.frag = c.frag[:0]
556		c.n, c.k = 0, 0
557	}
558
559	if c.n > 0 && c.k == c.n {
560		c.n, c.k = 0, 0
561		return c.frag, nil
562	}
563
564	return nil, nil
565}
566
567func (c *Conversation) generateDHCommit() []byte {
568	_, err := io.ReadFull(c.rand(), c.r[:])
569	if err != nil {
570		panic("otr: short read from random source")
571	}
572
573	var xBytes [dhPrivateBytes]byte
574	c.x = c.randMPI(xBytes[:])
575	c.gx = new(big.Int).Exp(g, c.x, p)
576	c.gy = nil
577	c.gxBytes = appendMPI(nil, c.gx)
578
579	h := sha256.New()
580	h.Write(c.gxBytes)
581	h.Sum(c.digest[:0])
582
583	aesCipher, err := aes.NewCipher(c.r[:])
584	if err != nil {
585		panic(err.Error())
586	}
587
588	var iv [aes.BlockSize]byte
589	ctr := cipher.NewCTR(aesCipher, iv[:])
590	ctr.XORKeyStream(c.gxBytes, c.gxBytes)
591
592	return c.serializeDHCommit()
593}
594
595func (c *Conversation) serializeDHCommit() []byte {
596	var ret []byte
597	ret = appendU16(ret, 2) // protocol version
598	ret = append(ret, msgTypeDHCommit)
599	ret = appendData(ret, c.gxBytes)
600	ret = appendData(ret, c.digest[:])
601	return ret
602}
603
604func (c *Conversation) processDHCommit(in []byte) error {
605	var ok1, ok2 bool
606	c.gxBytes, in, ok1 = getData(in)
607	digest, in, ok2 := getData(in)
608	if !ok1 || !ok2 || len(in) > 0 {
609		return errors.New("otr: corrupt DH commit message")
610	}
611	copy(c.digest[:], digest)
612	return nil
613}
614
615func (c *Conversation) compareToDHCommit(in []byte) (int, error) {
616	_, in, ok1 := getData(in)
617	digest, in, ok2 := getData(in)
618	if !ok1 || !ok2 || len(in) > 0 {
619		return 0, errors.New("otr: corrupt DH commit message")
620	}
621	return bytes.Compare(c.digest[:], digest), nil
622}
623
624func (c *Conversation) generateDHKey() []byte {
625	var yBytes [dhPrivateBytes]byte
626	c.y = c.randMPI(yBytes[:])
627	c.gy = new(big.Int).Exp(g, c.y, p)
628	return c.serializeDHKey()
629}
630
631func (c *Conversation) serializeDHKey() []byte {
632	var ret []byte
633	ret = appendU16(ret, 2) // protocol version
634	ret = append(ret, msgTypeDHKey)
635	ret = appendMPI(ret, c.gy)
636	return ret
637}
638
639func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) {
640	gy, in, ok := getMPI(in)
641	if !ok {
642		err = errors.New("otr: corrupt DH key message")
643		return
644	}
645	if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 {
646		err = errors.New("otr: DH value out of range")
647		return
648	}
649	if c.gy != nil {
650		isSame = c.gy.Cmp(gy) == 0
651		return
652	}
653	c.gy = gy
654	return
655}
656
657func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) {
658	var xb []byte
659	xb = c.PrivateKey.PublicKey.Serialize(xb)
660
661	var verifyData []byte
662	if xFirst {
663		verifyData = appendMPI(verifyData, c.gx)
664		verifyData = appendMPI(verifyData, c.gy)
665	} else {
666		verifyData = appendMPI(verifyData, c.gy)
667		verifyData = appendMPI(verifyData, c.gx)
668	}
669	verifyData = append(verifyData, xb...)
670	verifyData = appendU32(verifyData, c.myKeyId)
671
672	mac := hmac.New(sha256.New, keys.m1[:])
673	mac.Write(verifyData)
674	mb := mac.Sum(nil)
675
676	xb = appendU32(xb, c.myKeyId)
677	xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...)
678
679	aesCipher, err := aes.NewCipher(keys.c[:])
680	if err != nil {
681		panic(err.Error())
682	}
683	var iv [aes.BlockSize]byte
684	ctr := cipher.NewCTR(aesCipher, iv[:])
685	ctr.XORKeyStream(xb, xb)
686
687	mac = hmac.New(sha256.New, keys.m2[:])
688	encryptedSig := appendData(nil, xb)
689	mac.Write(encryptedSig)
690
691	return encryptedSig, mac.Sum(nil)
692}
693
694func (c *Conversation) generateRevealSig() []byte {
695	s := new(big.Int).Exp(c.gy, c.x, p)
696	c.calcAKEKeys(s)
697	c.myKeyId++
698
699	encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */)
700
701	c.myCurrentDHPub = c.gx
702	c.myCurrentDHPriv = c.x
703	c.rotateDHKeys()
704	incCounter(&c.myCounter)
705
706	var ret []byte
707	ret = appendU16(ret, 2)
708	ret = append(ret, msgTypeRevealSig)
709	ret = appendData(ret, c.r[:])
710	ret = append(ret, encryptedSig...)
711	ret = append(ret, mac[:20]...)
712	return ret
713}
714
715func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error {
716	mac := hmac.New(sha256.New, keys.m2[:])
717	mac.Write(appendData(nil, encryptedSig))
718	myMAC := mac.Sum(nil)[:20]
719
720	if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
721		return errors.New("bad signature MAC in encrypted signature")
722	}
723
724	aesCipher, err := aes.NewCipher(keys.c[:])
725	if err != nil {
726		panic(err.Error())
727	}
728	var iv [aes.BlockSize]byte
729	ctr := cipher.NewCTR(aesCipher, iv[:])
730	ctr.XORKeyStream(encryptedSig, encryptedSig)
731
732	sig := encryptedSig
733	sig, ok1 := c.TheirPublicKey.Parse(sig)
734	keyId, sig, ok2 := getU32(sig)
735	if !ok1 || !ok2 {
736		return errors.New("otr: corrupt encrypted signature")
737	}
738
739	var verifyData []byte
740	if xFirst {
741		verifyData = appendMPI(verifyData, c.gx)
742		verifyData = appendMPI(verifyData, c.gy)
743	} else {
744		verifyData = appendMPI(verifyData, c.gy)
745		verifyData = appendMPI(verifyData, c.gx)
746	}
747	verifyData = c.TheirPublicKey.Serialize(verifyData)
748	verifyData = appendU32(verifyData, keyId)
749
750	mac = hmac.New(sha256.New, keys.m1[:])
751	mac.Write(verifyData)
752	mb := mac.Sum(nil)
753
754	sig, ok1 = c.TheirPublicKey.Verify(mb, sig)
755	if !ok1 {
756		return errors.New("bad signature in encrypted signature")
757	}
758	if len(sig) > 0 {
759		return errors.New("corrupt encrypted signature")
760	}
761
762	c.theirKeyId = keyId
763	zero(c.theirLastCtr[:])
764	return nil
765}
766
767func (c *Conversation) processRevealSig(in []byte) error {
768	r, in, ok1 := getData(in)
769	encryptedSig, in, ok2 := getData(in)
770	theirMAC := in
771	if !ok1 || !ok2 || len(theirMAC) != 20 {
772		return errors.New("otr: corrupt reveal signature message")
773	}
774
775	aesCipher, err := aes.NewCipher(r)
776	if err != nil {
777		return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error())
778	}
779	var iv [aes.BlockSize]byte
780	ctr := cipher.NewCTR(aesCipher, iv[:])
781	ctr.XORKeyStream(c.gxBytes, c.gxBytes)
782	h := sha256.New()
783	h.Write(c.gxBytes)
784	digest := h.Sum(nil)
785	if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 {
786		return errors.New("otr: bad commit MAC in reveal signature message")
787	}
788	var rest []byte
789	c.gx, rest, ok1 = getMPI(c.gxBytes)
790	if !ok1 || len(rest) > 0 {
791		return errors.New("otr: gx corrupt after decryption")
792	}
793	if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 {
794		return errors.New("otr: DH value out of range")
795	}
796	s := new(big.Int).Exp(c.gx, c.y, p)
797	c.calcAKEKeys(s)
798
799	if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil {
800		return errors.New("otr: in reveal signature message: " + err.Error())
801	}
802
803	c.theirCurrentDHPub = c.gx
804	c.theirLastDHPub = nil
805
806	return nil
807}
808
809func (c *Conversation) generateSig() []byte {
810	c.myKeyId++
811
812	encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */)
813
814	c.myCurrentDHPub = c.gy
815	c.myCurrentDHPriv = c.y
816	c.rotateDHKeys()
817	incCounter(&c.myCounter)
818
819	var ret []byte
820	ret = appendU16(ret, 2)
821	ret = append(ret, msgTypeSig)
822	ret = append(ret, encryptedSig...)
823	ret = append(ret, mac[:macPrefixBytes]...)
824	return ret
825}
826
827func (c *Conversation) processSig(in []byte) error {
828	encryptedSig, in, ok1 := getData(in)
829	theirMAC := in
830	if !ok1 || len(theirMAC) != macPrefixBytes {
831		return errors.New("otr: corrupt signature message")
832	}
833
834	if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil {
835		return errors.New("otr: in signature message: " + err.Error())
836	}
837
838	c.theirCurrentDHPub = c.gy
839	c.theirLastDHPub = nil
840
841	return nil
842}
843
844func (c *Conversation) rotateDHKeys() {
845	// evict slots using our retired key id
846	for i := range c.keySlots {
847		slot := &c.keySlots[i]
848		if slot.used && slot.myKeyId == c.myKeyId-1 {
849			slot.used = false
850			c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
851		}
852	}
853
854	c.myLastDHPriv = c.myCurrentDHPriv
855	c.myLastDHPub = c.myCurrentDHPub
856
857	var xBytes [dhPrivateBytes]byte
858	c.myCurrentDHPriv = c.randMPI(xBytes[:])
859	c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p)
860	c.myKeyId++
861}
862
863func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) {
864	origIn := in
865	flags, in, ok1 := getU8(in)
866	theirKeyId, in, ok2 := getU32(in)
867	myKeyId, in, ok3 := getU32(in)
868	y, in, ok4 := getMPI(in)
869	counter, in, ok5 := getNBytes(in, 8)
870	encrypted, in, ok6 := getData(in)
871	macedData := origIn[:len(origIn)-len(in)]
872	theirMAC, in, ok7 := getNBytes(in, macPrefixBytes)
873	_, in, ok8 := getData(in)
874	if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 {
875		err = errors.New("otr: corrupt data message")
876		return
877	}
878
879	ignoreErrors := flags&1 != 0
880
881	slot, err := c.calcDataKeys(myKeyId, theirKeyId)
882	if err != nil {
883		if ignoreErrors {
884			err = nil
885		}
886		return
887	}
888
889	mac := hmac.New(sha1.New, slot.recvMACKey)
890	mac.Write([]byte{0, 2, 3})
891	mac.Write(macedData)
892	myMAC := mac.Sum(nil)
893	if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
894		if !ignoreErrors {
895			err = errors.New("otr: bad MAC on data message")
896		}
897		return
898	}
899
900	if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 {
901		err = errors.New("otr: counter regressed")
902		return
903	}
904	copy(slot.theirLastCtr[:], counter)
905
906	var iv [aes.BlockSize]byte
907	copy(iv[:], counter)
908	aesCipher, err := aes.NewCipher(slot.recvAESKey)
909	if err != nil {
910		panic(err.Error())
911	}
912	ctr := cipher.NewCTR(aesCipher, iv[:])
913	ctr.XORKeyStream(encrypted, encrypted)
914	decrypted := encrypted
915
916	if myKeyId == c.myKeyId {
917		c.rotateDHKeys()
918	}
919	if theirKeyId == c.theirKeyId {
920		// evict slots using their retired key id
921		for i := range c.keySlots {
922			slot := &c.keySlots[i]
923			if slot.used && slot.theirKeyId == theirKeyId-1 {
924				slot.used = false
925				c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
926			}
927		}
928
929		c.theirLastDHPub = c.theirCurrentDHPub
930		c.theirKeyId++
931		c.theirCurrentDHPub = y
932	}
933
934	if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 {
935		out = decrypted[:nulPos]
936		tlvData := decrypted[nulPos+1:]
937		for len(tlvData) > 0 {
938			var t tlv
939			var ok1, ok2, ok3 bool
940
941			t.typ, tlvData, ok1 = getU16(tlvData)
942			t.length, tlvData, ok2 = getU16(tlvData)
943			t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length))
944			if !ok1 || !ok2 || !ok3 {
945				err = errors.New("otr: corrupt tlv data")
946				return
947			}
948			tlvs = append(tlvs, t)
949		}
950	} else {
951		out = decrypted
952	}
953
954	return
955}
956
957func (c *Conversation) generateData(msg []byte, extra *tlv) []byte {
958	slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId)
959	if err != nil {
960		panic("otr: failed to generate sending keys: " + err.Error())
961	}
962
963	var plaintext []byte
964	plaintext = append(plaintext, msg...)
965	plaintext = append(plaintext, 0)
966
967	padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity)
968	plaintext = appendU16(plaintext, tlvTypePadding)
969	plaintext = appendU16(plaintext, uint16(padding))
970	for i := 0; i < padding; i++ {
971		plaintext = append(plaintext, 0)
972	}
973
974	if extra != nil {
975		plaintext = appendU16(plaintext, extra.typ)
976		plaintext = appendU16(plaintext, uint16(len(extra.data)))
977		plaintext = append(plaintext, extra.data...)
978	}
979
980	encrypted := make([]byte, len(plaintext))
981
982	var iv [aes.BlockSize]byte
983	copy(iv[:], c.myCounter[:])
984	aesCipher, err := aes.NewCipher(slot.sendAESKey)
985	if err != nil {
986		panic(err.Error())
987	}
988	ctr := cipher.NewCTR(aesCipher, iv[:])
989	ctr.XORKeyStream(encrypted, plaintext)
990
991	var ret []byte
992	ret = appendU16(ret, 2)
993	ret = append(ret, msgTypeData)
994	ret = append(ret, 0 /* flags */)
995	ret = appendU32(ret, c.myKeyId-1)
996	ret = appendU32(ret, c.theirKeyId)
997	ret = appendMPI(ret, c.myCurrentDHPub)
998	ret = append(ret, c.myCounter[:]...)
999	ret = appendData(ret, encrypted)
1000
1001	mac := hmac.New(sha1.New, slot.sendMACKey)
1002	mac.Write(ret)
1003	ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...)
1004	ret = appendData(ret, c.oldMACs)
1005	c.oldMACs = nil
1006	incCounter(&c.myCounter)
1007
1008	return ret
1009}
1010
1011func incCounter(counter *[8]byte) {
1012	for i := 7; i >= 0; i-- {
1013		counter[i]++
1014		if counter[i] > 0 {
1015			break
1016		}
1017	}
1018}
1019
1020// calcDataKeys computes the keys used to encrypt a data message given the key
1021// IDs.
1022func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) {
1023	// Check for a cache hit.
1024	for i := range c.keySlots {
1025		slot = &c.keySlots[i]
1026		if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId {
1027			return
1028		}
1029	}
1030
1031	// Find an empty slot to write into.
1032	slot = nil
1033	for i := range c.keySlots {
1034		if !c.keySlots[i].used {
1035			slot = &c.keySlots[i]
1036			break
1037		}
1038	}
1039	if slot == nil {
1040		return nil, errors.New("otr: internal error: no more key slots")
1041	}
1042
1043	var myPriv, myPub, theirPub *big.Int
1044
1045	if myKeyId == c.myKeyId {
1046		myPriv = c.myCurrentDHPriv
1047		myPub = c.myCurrentDHPub
1048	} else if myKeyId == c.myKeyId-1 {
1049		myPriv = c.myLastDHPriv
1050		myPub = c.myLastDHPub
1051	} else {
1052		err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10))
1053		return
1054	}
1055
1056	if theirKeyId == c.theirKeyId {
1057		theirPub = c.theirCurrentDHPub
1058	} else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil {
1059		theirPub = c.theirLastDHPub
1060	} else {
1061		err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10))
1062		return
1063	}
1064
1065	var sendPrefixByte, recvPrefixByte [1]byte
1066
1067	if myPub.Cmp(theirPub) > 0 {
1068		// we're the high end
1069		sendPrefixByte[0], recvPrefixByte[0] = 1, 2
1070	} else {
1071		// we're the low end
1072		sendPrefixByte[0], recvPrefixByte[0] = 2, 1
1073	}
1074
1075	s := new(big.Int).Exp(theirPub, myPriv, p)
1076	sBytes := appendMPI(nil, s)
1077
1078	h := sha1.New()
1079	h.Write(sendPrefixByte[:])
1080	h.Write(sBytes)
1081	slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16]
1082
1083	h.Reset()
1084	h.Write(slot.sendAESKey)
1085	slot.sendMACKey = h.Sum(slot.sendMACKey[:0])
1086
1087	h.Reset()
1088	h.Write(recvPrefixByte[:])
1089	h.Write(sBytes)
1090	slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16]
1091
1092	h.Reset()
1093	h.Write(slot.recvAESKey)
1094	slot.recvMACKey = h.Sum(slot.recvMACKey[:0])
1095
1096	slot.theirKeyId = theirKeyId
1097	slot.myKeyId = myKeyId
1098	slot.used = true
1099
1100	zero(slot.theirLastCtr[:])
1101	return
1102}
1103
1104func (c *Conversation) calcAKEKeys(s *big.Int) {
1105	mpi := appendMPI(nil, s)
1106	h := sha256.New()
1107
1108	var cBytes [32]byte
1109	hashWithPrefix(c.SSID[:], 0, mpi, h)
1110
1111	hashWithPrefix(cBytes[:], 1, mpi, h)
1112	copy(c.revealKeys.c[:], cBytes[:16])
1113	copy(c.sigKeys.c[:], cBytes[16:])
1114
1115	hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h)
1116	hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h)
1117	hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h)
1118	hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h)
1119}
1120
1121func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) {
1122	h.Reset()
1123	var p [1]byte
1124	p[0] = prefix
1125	h.Write(p[:])
1126	h.Write(in)
1127	if len(out) == h.Size() {
1128		h.Sum(out[:0])
1129	} else {
1130		digest := h.Sum(nil)
1131		copy(out, digest)
1132	}
1133}
1134
1135func (c *Conversation) encode(msg []byte) [][]byte {
1136	b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1)
1137	base64.StdEncoding.Encode(b64[len(msgPrefix):], msg)
1138	copy(b64, msgPrefix)
1139	b64[len(b64)-1] = '.'
1140
1141	if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize {
1142		// We can encode this in a single fragment.
1143		return [][]byte{b64}
1144	}
1145
1146	// We have to fragment this message.
1147	var ret [][]byte
1148	bytesPerFragment := c.FragmentSize - minFragmentSize
1149	numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment
1150
1151	for i := 0; i < numFragments; i++ {
1152		frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",")
1153		todo := bytesPerFragment
1154		if todo > len(b64) {
1155			todo = len(b64)
1156		}
1157		frag = append(frag, b64[:todo]...)
1158		b64 = b64[todo:]
1159		frag = append(frag, ',')
1160		ret = append(ret, frag)
1161	}
1162
1163	return ret
1164}
1165
1166func (c *Conversation) reset() {
1167	c.myKeyId = 0
1168
1169	for i := range c.keySlots {
1170		c.keySlots[i].used = false
1171	}
1172}
1173
1174type PublicKey struct {
1175	dsa.PublicKey
1176}
1177
1178func (pk *PublicKey) Parse(in []byte) ([]byte, bool) {
1179	var ok bool
1180	var pubKeyType uint16
1181
1182	if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 {
1183		return nil, false
1184	}
1185	if pk.P, in, ok = getMPI(in); !ok {
1186		return nil, false
1187	}
1188	if pk.Q, in, ok = getMPI(in); !ok {
1189		return nil, false
1190	}
1191	if pk.G, in, ok = getMPI(in); !ok {
1192		return nil, false
1193	}
1194	if pk.Y, in, ok = getMPI(in); !ok {
1195		return nil, false
1196	}
1197
1198	return in, true
1199}
1200
1201func (pk *PublicKey) Serialize(in []byte) []byte {
1202	in = appendU16(in, 0)
1203	in = appendMPI(in, pk.P)
1204	in = appendMPI(in, pk.Q)
1205	in = appendMPI(in, pk.G)
1206	in = appendMPI(in, pk.Y)
1207	return in
1208}
1209
1210// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey.
1211func (pk *PublicKey) Fingerprint() []byte {
1212	b := pk.Serialize(nil)
1213	h := sha1.New()
1214	h.Write(b[2:])
1215	return h.Sum(nil)
1216}
1217
1218func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) {
1219	if len(sig) != 2*dsaSubgroupBytes {
1220		return nil, false
1221	}
1222	r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes])
1223	s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:])
1224	ok := dsa.Verify(&pk.PublicKey, hashed, r, s)
1225	return sig[dsaSubgroupBytes*2:], ok
1226}
1227
1228type PrivateKey struct {
1229	PublicKey
1230	dsa.PrivateKey
1231}
1232
1233func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte {
1234	r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed)
1235	if err != nil {
1236		panic(err.Error())
1237	}
1238	rBytes := r.Bytes()
1239	sBytes := s.Bytes()
1240	if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes {
1241		panic("DSA signature too large")
1242	}
1243
1244	out := make([]byte, 2*dsaSubgroupBytes)
1245	copy(out[dsaSubgroupBytes-len(rBytes):], rBytes)
1246	copy(out[len(out)-len(sBytes):], sBytes)
1247	return out
1248}
1249
1250func (priv *PrivateKey) Serialize(in []byte) []byte {
1251	in = priv.PublicKey.Serialize(in)
1252	in = appendMPI(in, priv.PrivateKey.X)
1253	return in
1254}
1255
1256func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) {
1257	in, ok := priv.PublicKey.Parse(in)
1258	if !ok {
1259		return in, ok
1260	}
1261	priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey
1262	priv.PrivateKey.X, in, ok = getMPI(in)
1263	return in, ok
1264}
1265
1266func (priv *PrivateKey) Generate(rand io.Reader) {
1267	if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil {
1268		panic(err.Error())
1269	}
1270	if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil {
1271		panic(err.Error())
1272	}
1273	priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
1274}
1275
1276func notHex(r rune) bool {
1277	if r >= '0' && r <= '9' ||
1278		r >= 'a' && r <= 'f' ||
1279		r >= 'A' && r <= 'F' {
1280		return false
1281	}
1282
1283	return true
1284}
1285
1286// Import parses the contents of a libotr private key file.
1287func (priv *PrivateKey) Import(in []byte) bool {
1288	mpiStart := []byte(" #")
1289
1290	mpis := make([]*big.Int, 5)
1291
1292	for i := 0; i < len(mpis); i++ {
1293		start := bytes.Index(in, mpiStart)
1294		if start == -1 {
1295			return false
1296		}
1297		in = in[start+len(mpiStart):]
1298		end := bytes.IndexFunc(in, notHex)
1299		if end == -1 {
1300			return false
1301		}
1302		hexBytes := in[:end]
1303		in = in[end:]
1304
1305		if len(hexBytes)&1 != 0 {
1306			return false
1307		}
1308
1309		mpiBytes := make([]byte, len(hexBytes)/2)
1310		if _, err := hex.Decode(mpiBytes, hexBytes); err != nil {
1311			return false
1312		}
1313
1314		mpis[i] = new(big.Int).SetBytes(mpiBytes)
1315	}
1316
1317	for _, mpi := range mpis {
1318		if mpi.Sign() <= 0 {
1319			return false
1320		}
1321	}
1322
1323	priv.PrivateKey.P = mpis[0]
1324	priv.PrivateKey.Q = mpis[1]
1325	priv.PrivateKey.G = mpis[2]
1326	priv.PrivateKey.Y = mpis[3]
1327	priv.PrivateKey.X = mpis[4]
1328	priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
1329
1330	a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P)
1331	return a.Cmp(priv.PrivateKey.Y) == 0
1332}
1333
1334func getU8(in []byte) (uint8, []byte, bool) {
1335	if len(in) < 1 {
1336		return 0, in, false
1337	}
1338	return in[0], in[1:], true
1339}
1340
1341func getU16(in []byte) (uint16, []byte, bool) {
1342	if len(in) < 2 {
1343		return 0, in, false
1344	}
1345	r := uint16(in[0])<<8 | uint16(in[1])
1346	return r, in[2:], true
1347}
1348
1349func getU32(in []byte) (uint32, []byte, bool) {
1350	if len(in) < 4 {
1351		return 0, in, false
1352	}
1353	r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
1354	return r, in[4:], true
1355}
1356
1357func getMPI(in []byte) (*big.Int, []byte, bool) {
1358	l, in, ok := getU32(in)
1359	if !ok || uint32(len(in)) < l {
1360		return nil, in, false
1361	}
1362	r := new(big.Int).SetBytes(in[:l])
1363	return r, in[l:], true
1364}
1365
1366func getData(in []byte) ([]byte, []byte, bool) {
1367	l, in, ok := getU32(in)
1368	if !ok || uint32(len(in)) < l {
1369		return nil, in, false
1370	}
1371	return in[:l], in[l:], true
1372}
1373
1374func getNBytes(in []byte, n int) ([]byte, []byte, bool) {
1375	if len(in) < n {
1376		return nil, in, false
1377	}
1378	return in[:n], in[n:], true
1379}
1380
1381func appendU16(out []byte, v uint16) []byte {
1382	out = append(out, byte(v>>8), byte(v))
1383	return out
1384}
1385
1386func appendU32(out []byte, v uint32) []byte {
1387	out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
1388	return out
1389}
1390
1391func appendData(out, v []byte) []byte {
1392	out = appendU32(out, uint32(len(v)))
1393	out = append(out, v...)
1394	return out
1395}
1396
1397func appendMPI(out []byte, v *big.Int) []byte {
1398	vBytes := v.Bytes()
1399	out = appendU32(out, uint32(len(vBytes)))
1400	out = append(out, vBytes...)
1401	return out
1402}
1403
1404func appendMPIs(out []byte, mpis ...*big.Int) []byte {
1405	for _, mpi := range mpis {
1406		out = appendMPI(out, mpi)
1407	}
1408	return out
1409}
1410
1411func zero(b []byte) {
1412	for i := range b {
1413		b[i] = 0
1414	}
1415}
1416