~nskaggs/+junk/juju-packaging-test

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/otr/otr.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-27 20:23:11 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161027202311-sux4jk2o73p1d6rg
Re-add src

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
7
package otr // import "golang.org/x/crypto/otr"
 
8
 
 
9
import (
 
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.
 
29
type SecurityChange int
 
30
 
 
31
const (
 
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.
 
53
var QueryMessage = "?OTRv2?"
 
54
 
 
55
// ErrorPrefix can be used to make an OTR error by appending an error message
 
56
// to it.
 
57
var ErrorPrefix = "?OTR Error:"
 
58
 
 
59
var (
 
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.
 
68
func 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
 
 
107
const (
 
108
        statePlaintext = iota
 
109
        stateEncrypted
 
110
        stateFinished
 
111
)
 
112
 
 
113
const (
 
114
        authStateNone = iota
 
115
        authStateAwaitingDHKey
 
116
        authStateAwaitingRevealSig
 
117
        authStateAwaitingSig
 
118
)
 
119
 
 
120
const (
 
121
        msgTypeDHCommit  = 2
 
122
        msgTypeData      = 3
 
123
        msgTypeDHKey     = 10
 
124
        msgTypeRevealSig = 17
 
125
        msgTypeSig       = 18
 
126
)
 
127
 
 
128
const (
 
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.
 
143
var (
 
144
        p       *big.Int // group prime
 
145
        g       *big.Int // group generator
 
146
        q       *big.Int // group order
 
147
        pMinus2 *big.Int
 
148
)
 
149
 
 
150
func 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.
 
164
type 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.
 
213
type 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.
 
226
type akeKeys struct {
 
227
        c      [16]byte
 
228
        m1, m2 [32]byte
 
229
}
 
230
 
 
231
func (c *Conversation) rand() io.Reader {
 
232
        if c.Rand != nil {
 
233
                return c.Rand
 
234
        }
 
235
        return rand.Reader
 
236
}
 
237
 
 
238
func (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.
 
248
type tlv struct {
 
249
        typ, length uint16
 
250
        data        []byte
 
251
}
 
252
 
 
253
const (
 
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.
 
268
func (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.myKeyId = 0
 
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.myKeyId = 0
 
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.myKeyId = 0
 
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.myKeyId = 0
 
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
                                } else if err == smpFailureError {
 
421
                                        err = nil
 
422
                                        change = SMPFailed
 
423
                                        return
 
424
                                }
 
425
                                if complete {
 
426
                                        change = SMPComplete
 
427
                                }
 
428
                                if reply.typ != 0 {
 
429
                                        toSend = c.encode(c.generateData(nil, &reply))
 
430
                                }
 
431
                                break EachTLV
 
432
                        default:
 
433
                                // skip unknown TLVs
 
434
                        }
 
435
                }
 
436
        default:
 
437
                err = errors.New("otr: unknown message type " + strconv.Itoa(msgType))
 
438
        }
 
439
 
 
440
        return
 
441
}
 
442
 
 
443
// Send takes a human readable message from the local user, possibly encrypts
 
444
// it and returns zero one or more messages to send to the peer.
 
445
func (c *Conversation) Send(msg []byte) ([][]byte, error) {
 
446
        switch c.state {
 
447
        case statePlaintext:
 
448
                return [][]byte{msg}, nil
 
449
        case stateEncrypted:
 
450
                return c.encode(c.generateData(msg, nil)), nil
 
451
        case stateFinished:
 
452
                return nil, errors.New("otr: cannot send message because secure conversation has finished")
 
453
        }
 
454
 
 
455
        return nil, errors.New("otr: cannot send message in current state")
 
456
}
 
457
 
 
458
// SMPQuestion returns the human readable challenge question from the peer.
 
459
// It's only valid after Receive has returned SMPSecretNeeded.
 
460
func (c *Conversation) SMPQuestion() string {
 
461
        return c.smp.question
 
462
}
 
463
 
 
464
// Authenticate begins an authentication with the peer. Authentication involves
 
465
// an optional challenge message and a shared secret. The authentication
 
466
// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which
 
467
// indicates that a new authentication is happening and thus this one was
 
468
// aborted) or SMPFailed.
 
469
func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) {
 
470
        if c.state != stateEncrypted {
 
471
                err = errors.New("otr: can't authenticate a peer without a secure conversation established")
 
472
                return
 
473
        }
 
474
 
 
475
        if c.smp.saved != nil {
 
476
                c.calcSMPSecret(mutualSecret, false /* they started it */)
 
477
 
 
478
                var out tlv
 
479
                var complete bool
 
480
                out, complete, err = c.processSMP(*c.smp.saved)
 
481
                if complete {
 
482
                        panic("SMP completed on the first message")
 
483
                }
 
484
                c.smp.saved = nil
 
485
                if out.typ != 0 {
 
486
                        toSend = c.encode(c.generateData(nil, &out))
 
487
                }
 
488
                return
 
489
        }
 
490
 
 
491
        c.calcSMPSecret(mutualSecret, true /* we started it */)
 
492
        outs := c.startSMP(question)
 
493
        for _, out := range outs {
 
494
                toSend = append(toSend, c.encode(c.generateData(nil, &out))...)
 
495
        }
 
496
        return
 
497
}
 
498
 
 
499
// End ends a secure conversation by generating a termination message for
 
500
// the peer and switches to unencrypted communication.
 
501
func (c *Conversation) End() (toSend [][]byte) {
 
502
        switch c.state {
 
503
        case statePlaintext:
 
504
                return nil
 
505
        case stateEncrypted:
 
506
                c.state = statePlaintext
 
507
                return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected}))
 
508
        case stateFinished:
 
509
                c.state = statePlaintext
 
510
                return nil
 
511
        }
 
512
        panic("unreachable")
 
513
}
 
514
 
 
515
// IsEncrypted returns true if a message passed to Send would be encrypted
 
516
// before transmission. This result remains valid until the next call to
 
517
// Receive or End, which may change the state of the Conversation.
 
518
func (c *Conversation) IsEncrypted() bool {
 
519
        return c.state == stateEncrypted
 
520
}
 
521
 
 
522
var fragmentError = errors.New("otr: invalid OTR fragment")
 
523
 
 
524
// processFragment processes a fragmented OTR message and possibly returns a
 
525
// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is
 
526
// the fragment number (starting from 1), n is the number of fragments in this
 
527
// message and msg is a substring of the base64 encoded message.
 
528
func (c *Conversation) processFragment(in []byte) (out []byte, err error) {
 
529
        in = in[len(fragmentPrefix):] // remove "?OTR,"
 
530
        parts := bytes.Split(in, fragmentPartSeparator)
 
531
        if len(parts) != 4 || len(parts[3]) != 0 {
 
532
                return nil, fragmentError
 
533
        }
 
534
 
 
535
        k, err := strconv.Atoi(string(parts[0]))
 
536
        if err != nil {
 
537
                return nil, fragmentError
 
538
        }
 
539
 
 
540
        n, err := strconv.Atoi(string(parts[1]))
 
541
        if err != nil {
 
542
                return nil, fragmentError
 
543
        }
 
544
 
 
545
        if k < 1 || n < 1 || k > n {
 
546
                return nil, fragmentError
 
547
        }
 
548
 
 
549
        if k == 1 {
 
550
                c.frag = append(c.frag[:0], parts[2]...)
 
551
                c.k, c.n = k, n
 
552
        } else if n == c.n && k == c.k+1 {
 
553
                c.frag = append(c.frag, parts[2]...)
 
554
                c.k++
 
555
        } else {
 
556
                c.frag = c.frag[:0]
 
557
                c.n, c.k = 0, 0
 
558
        }
 
559
 
 
560
        if c.n > 0 && c.k == c.n {
 
561
                c.n, c.k = 0, 0
 
562
                return c.frag, nil
 
563
        }
 
564
 
 
565
        return nil, nil
 
566
}
 
567
 
 
568
func (c *Conversation) generateDHCommit() []byte {
 
569
        _, err := io.ReadFull(c.rand(), c.r[:])
 
570
        if err != nil {
 
571
                panic("otr: short read from random source")
 
572
        }
 
573
 
 
574
        var xBytes [dhPrivateBytes]byte
 
575
        c.x = c.randMPI(xBytes[:])
 
576
        c.gx = new(big.Int).Exp(g, c.x, p)
 
577
        c.gy = nil
 
578
        c.gxBytes = appendMPI(nil, c.gx)
 
579
 
 
580
        h := sha256.New()
 
581
        h.Write(c.gxBytes)
 
582
        h.Sum(c.digest[:0])
 
583
 
 
584
        aesCipher, err := aes.NewCipher(c.r[:])
 
585
        if err != nil {
 
586
                panic(err.Error())
 
587
        }
 
588
 
 
589
        var iv [aes.BlockSize]byte
 
590
        ctr := cipher.NewCTR(aesCipher, iv[:])
 
591
        ctr.XORKeyStream(c.gxBytes, c.gxBytes)
 
592
 
 
593
        return c.serializeDHCommit()
 
594
}
 
595
 
 
596
func (c *Conversation) serializeDHCommit() []byte {
 
597
        var ret []byte
 
598
        ret = appendU16(ret, 2) // protocol version
 
599
        ret = append(ret, msgTypeDHCommit)
 
600
        ret = appendData(ret, c.gxBytes)
 
601
        ret = appendData(ret, c.digest[:])
 
602
        return ret
 
603
}
 
604
 
 
605
func (c *Conversation) processDHCommit(in []byte) error {
 
606
        var ok1, ok2 bool
 
607
        c.gxBytes, in, ok1 = getData(in)
 
608
        digest, in, ok2 := getData(in)
 
609
        if !ok1 || !ok2 || len(in) > 0 {
 
610
                return errors.New("otr: corrupt DH commit message")
 
611
        }
 
612
        copy(c.digest[:], digest)
 
613
        return nil
 
614
}
 
615
 
 
616
func (c *Conversation) compareToDHCommit(in []byte) (int, error) {
 
617
        _, in, ok1 := getData(in)
 
618
        digest, in, ok2 := getData(in)
 
619
        if !ok1 || !ok2 || len(in) > 0 {
 
620
                return 0, errors.New("otr: corrupt DH commit message")
 
621
        }
 
622
        return bytes.Compare(c.digest[:], digest), nil
 
623
}
 
624
 
 
625
func (c *Conversation) generateDHKey() []byte {
 
626
        var yBytes [dhPrivateBytes]byte
 
627
        c.y = c.randMPI(yBytes[:])
 
628
        c.gy = new(big.Int).Exp(g, c.y, p)
 
629
        return c.serializeDHKey()
 
630
}
 
631
 
 
632
func (c *Conversation) serializeDHKey() []byte {
 
633
        var ret []byte
 
634
        ret = appendU16(ret, 2) // protocol version
 
635
        ret = append(ret, msgTypeDHKey)
 
636
        ret = appendMPI(ret, c.gy)
 
637
        return ret
 
638
}
 
639
 
 
640
func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) {
 
641
        gy, in, ok := getMPI(in)
 
642
        if !ok {
 
643
                err = errors.New("otr: corrupt DH key message")
 
644
                return
 
645
        }
 
646
        if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 {
 
647
                err = errors.New("otr: DH value out of range")
 
648
                return
 
649
        }
 
650
        if c.gy != nil {
 
651
                isSame = c.gy.Cmp(gy) == 0
 
652
                return
 
653
        }
 
654
        c.gy = gy
 
655
        return
 
656
}
 
657
 
 
658
func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) {
 
659
        var xb []byte
 
660
        xb = c.PrivateKey.PublicKey.Serialize(xb)
 
661
 
 
662
        var verifyData []byte
 
663
        if xFirst {
 
664
                verifyData = appendMPI(verifyData, c.gx)
 
665
                verifyData = appendMPI(verifyData, c.gy)
 
666
        } else {
 
667
                verifyData = appendMPI(verifyData, c.gy)
 
668
                verifyData = appendMPI(verifyData, c.gx)
 
669
        }
 
670
        verifyData = append(verifyData, xb...)
 
671
        verifyData = appendU32(verifyData, c.myKeyId)
 
672
 
 
673
        mac := hmac.New(sha256.New, keys.m1[:])
 
674
        mac.Write(verifyData)
 
675
        mb := mac.Sum(nil)
 
676
 
 
677
        xb = appendU32(xb, c.myKeyId)
 
678
        xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...)
 
679
 
 
680
        aesCipher, err := aes.NewCipher(keys.c[:])
 
681
        if err != nil {
 
682
                panic(err.Error())
 
683
        }
 
684
        var iv [aes.BlockSize]byte
 
685
        ctr := cipher.NewCTR(aesCipher, iv[:])
 
686
        ctr.XORKeyStream(xb, xb)
 
687
 
 
688
        mac = hmac.New(sha256.New, keys.m2[:])
 
689
        encryptedSig := appendData(nil, xb)
 
690
        mac.Write(encryptedSig)
 
691
 
 
692
        return encryptedSig, mac.Sum(nil)
 
693
}
 
694
 
 
695
func (c *Conversation) generateRevealSig() []byte {
 
696
        s := new(big.Int).Exp(c.gy, c.x, p)
 
697
        c.calcAKEKeys(s)
 
698
        c.myKeyId++
 
699
 
 
700
        encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */)
 
701
 
 
702
        c.myCurrentDHPub = c.gx
 
703
        c.myCurrentDHPriv = c.x
 
704
        c.rotateDHKeys()
 
705
        incCounter(&c.myCounter)
 
706
 
 
707
        var ret []byte
 
708
        ret = appendU16(ret, 2)
 
709
        ret = append(ret, msgTypeRevealSig)
 
710
        ret = appendData(ret, c.r[:])
 
711
        ret = append(ret, encryptedSig...)
 
712
        ret = append(ret, mac[:20]...)
 
713
        return ret
 
714
}
 
715
 
 
716
func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error {
 
717
        mac := hmac.New(sha256.New, keys.m2[:])
 
718
        mac.Write(appendData(nil, encryptedSig))
 
719
        myMAC := mac.Sum(nil)[:20]
 
720
 
 
721
        if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
 
722
                return errors.New("bad signature MAC in encrypted signature")
 
723
        }
 
724
 
 
725
        aesCipher, err := aes.NewCipher(keys.c[:])
 
726
        if err != nil {
 
727
                panic(err.Error())
 
728
        }
 
729
        var iv [aes.BlockSize]byte
 
730
        ctr := cipher.NewCTR(aesCipher, iv[:])
 
731
        ctr.XORKeyStream(encryptedSig, encryptedSig)
 
732
 
 
733
        sig := encryptedSig
 
734
        sig, ok1 := c.TheirPublicKey.Parse(sig)
 
735
        keyId, sig, ok2 := getU32(sig)
 
736
        if !ok1 || !ok2 {
 
737
                return errors.New("otr: corrupt encrypted signature")
 
738
        }
 
739
 
 
740
        var verifyData []byte
 
741
        if xFirst {
 
742
                verifyData = appendMPI(verifyData, c.gx)
 
743
                verifyData = appendMPI(verifyData, c.gy)
 
744
        } else {
 
745
                verifyData = appendMPI(verifyData, c.gy)
 
746
                verifyData = appendMPI(verifyData, c.gx)
 
747
        }
 
748
        verifyData = c.TheirPublicKey.Serialize(verifyData)
 
749
        verifyData = appendU32(verifyData, keyId)
 
750
 
 
751
        mac = hmac.New(sha256.New, keys.m1[:])
 
752
        mac.Write(verifyData)
 
753
        mb := mac.Sum(nil)
 
754
 
 
755
        sig, ok1 = c.TheirPublicKey.Verify(mb, sig)
 
756
        if !ok1 {
 
757
                return errors.New("bad signature in encrypted signature")
 
758
        }
 
759
        if len(sig) > 0 {
 
760
                return errors.New("corrupt encrypted signature")
 
761
        }
 
762
 
 
763
        c.theirKeyId = keyId
 
764
        zero(c.theirLastCtr[:])
 
765
        return nil
 
766
}
 
767
 
 
768
func (c *Conversation) processRevealSig(in []byte) error {
 
769
        r, in, ok1 := getData(in)
 
770
        encryptedSig, in, ok2 := getData(in)
 
771
        theirMAC := in
 
772
        if !ok1 || !ok2 || len(theirMAC) != 20 {
 
773
                return errors.New("otr: corrupt reveal signature message")
 
774
        }
 
775
 
 
776
        aesCipher, err := aes.NewCipher(r)
 
777
        if err != nil {
 
778
                return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error())
 
779
        }
 
780
        var iv [aes.BlockSize]byte
 
781
        ctr := cipher.NewCTR(aesCipher, iv[:])
 
782
        ctr.XORKeyStream(c.gxBytes, c.gxBytes)
 
783
        h := sha256.New()
 
784
        h.Write(c.gxBytes)
 
785
        digest := h.Sum(nil)
 
786
        if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 {
 
787
                return errors.New("otr: bad commit MAC in reveal signature message")
 
788
        }
 
789
        var rest []byte
 
790
        c.gx, rest, ok1 = getMPI(c.gxBytes)
 
791
        if !ok1 || len(rest) > 0 {
 
792
                return errors.New("otr: gx corrupt after decryption")
 
793
        }
 
794
        if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 {
 
795
                return errors.New("otr: DH value out of range")
 
796
        }
 
797
        s := new(big.Int).Exp(c.gx, c.y, p)
 
798
        c.calcAKEKeys(s)
 
799
 
 
800
        if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil {
 
801
                return errors.New("otr: in reveal signature message: " + err.Error())
 
802
        }
 
803
 
 
804
        c.theirCurrentDHPub = c.gx
 
805
        c.theirLastDHPub = nil
 
806
 
 
807
        return nil
 
808
}
 
809
 
 
810
func (c *Conversation) generateSig() []byte {
 
811
        c.myKeyId++
 
812
 
 
813
        encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */)
 
814
 
 
815
        c.myCurrentDHPub = c.gy
 
816
        c.myCurrentDHPriv = c.y
 
817
        c.rotateDHKeys()
 
818
        incCounter(&c.myCounter)
 
819
 
 
820
        var ret []byte
 
821
        ret = appendU16(ret, 2)
 
822
        ret = append(ret, msgTypeSig)
 
823
        ret = append(ret, encryptedSig...)
 
824
        ret = append(ret, mac[:macPrefixBytes]...)
 
825
        return ret
 
826
}
 
827
 
 
828
func (c *Conversation) processSig(in []byte) error {
 
829
        encryptedSig, in, ok1 := getData(in)
 
830
        theirMAC := in
 
831
        if !ok1 || len(theirMAC) != macPrefixBytes {
 
832
                return errors.New("otr: corrupt signature message")
 
833
        }
 
834
 
 
835
        if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil {
 
836
                return errors.New("otr: in signature message: " + err.Error())
 
837
        }
 
838
 
 
839
        c.theirCurrentDHPub = c.gy
 
840
        c.theirLastDHPub = nil
 
841
 
 
842
        return nil
 
843
}
 
844
 
 
845
func (c *Conversation) rotateDHKeys() {
 
846
        // evict slots using our retired key id
 
847
        for i := range c.keySlots {
 
848
                slot := &c.keySlots[i]
 
849
                if slot.used && slot.myKeyId == c.myKeyId-1 {
 
850
                        slot.used = false
 
851
                        c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
 
852
                }
 
853
        }
 
854
 
 
855
        c.myLastDHPriv = c.myCurrentDHPriv
 
856
        c.myLastDHPub = c.myCurrentDHPub
 
857
 
 
858
        var xBytes [dhPrivateBytes]byte
 
859
        c.myCurrentDHPriv = c.randMPI(xBytes[:])
 
860
        c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p)
 
861
        c.myKeyId++
 
862
}
 
863
 
 
864
func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) {
 
865
        origIn := in
 
866
        flags, in, ok1 := getU8(in)
 
867
        theirKeyId, in, ok2 := getU32(in)
 
868
        myKeyId, in, ok3 := getU32(in)
 
869
        y, in, ok4 := getMPI(in)
 
870
        counter, in, ok5 := getNBytes(in, 8)
 
871
        encrypted, in, ok6 := getData(in)
 
872
        macedData := origIn[:len(origIn)-len(in)]
 
873
        theirMAC, in, ok7 := getNBytes(in, macPrefixBytes)
 
874
        _, in, ok8 := getData(in)
 
875
        if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 {
 
876
                err = errors.New("otr: corrupt data message")
 
877
                return
 
878
        }
 
879
 
 
880
        ignoreErrors := flags&1 != 0
 
881
 
 
882
        slot, err := c.calcDataKeys(myKeyId, theirKeyId)
 
883
        if err != nil {
 
884
                if ignoreErrors {
 
885
                        err = nil
 
886
                }
 
887
                return
 
888
        }
 
889
 
 
890
        mac := hmac.New(sha1.New, slot.recvMACKey)
 
891
        mac.Write([]byte{0, 2, 3})
 
892
        mac.Write(macedData)
 
893
        myMAC := mac.Sum(nil)
 
894
        if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
 
895
                if !ignoreErrors {
 
896
                        err = errors.New("otr: bad MAC on data message")
 
897
                }
 
898
                return
 
899
        }
 
900
 
 
901
        if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 {
 
902
                err = errors.New("otr: counter regressed")
 
903
                return
 
904
        }
 
905
        copy(slot.theirLastCtr[:], counter)
 
906
 
 
907
        var iv [aes.BlockSize]byte
 
908
        copy(iv[:], counter)
 
909
        aesCipher, err := aes.NewCipher(slot.recvAESKey)
 
910
        if err != nil {
 
911
                panic(err.Error())
 
912
        }
 
913
        ctr := cipher.NewCTR(aesCipher, iv[:])
 
914
        ctr.XORKeyStream(encrypted, encrypted)
 
915
        decrypted := encrypted
 
916
 
 
917
        if myKeyId == c.myKeyId {
 
918
                c.rotateDHKeys()
 
919
        }
 
920
        if theirKeyId == c.theirKeyId {
 
921
                // evict slots using their retired key id
 
922
                for i := range c.keySlots {
 
923
                        slot := &c.keySlots[i]
 
924
                        if slot.used && slot.theirKeyId == theirKeyId-1 {
 
925
                                slot.used = false
 
926
                                c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
 
927
                        }
 
928
                }
 
929
 
 
930
                c.theirLastDHPub = c.theirCurrentDHPub
 
931
                c.theirKeyId++
 
932
                c.theirCurrentDHPub = y
 
933
        }
 
934
 
 
935
        if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 {
 
936
                out = decrypted[:nulPos]
 
937
                tlvData := decrypted[nulPos+1:]
 
938
                for len(tlvData) > 0 {
 
939
                        var t tlv
 
940
                        var ok1, ok2, ok3 bool
 
941
 
 
942
                        t.typ, tlvData, ok1 = getU16(tlvData)
 
943
                        t.length, tlvData, ok2 = getU16(tlvData)
 
944
                        t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length))
 
945
                        if !ok1 || !ok2 || !ok3 {
 
946
                                err = errors.New("otr: corrupt tlv data")
 
947
                        }
 
948
                        tlvs = append(tlvs, t)
 
949
                }
 
950
        } else {
 
951
                out = decrypted
 
952
        }
 
953
 
 
954
        return
 
955
}
 
956
 
 
957
func (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
 
 
1011
func 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.
 
1022
func (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
                err = errors.New("otr: internal error: no key slots")
 
1041
                return
 
1042
        }
 
1043
 
 
1044
        var myPriv, myPub, theirPub *big.Int
 
1045
 
 
1046
        if myKeyId == c.myKeyId {
 
1047
                myPriv = c.myCurrentDHPriv
 
1048
                myPub = c.myCurrentDHPub
 
1049
        } else if myKeyId == c.myKeyId-1 {
 
1050
                myPriv = c.myLastDHPriv
 
1051
                myPub = c.myLastDHPub
 
1052
        } else {
 
1053
                err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10))
 
1054
                return
 
1055
        }
 
1056
 
 
1057
        if theirKeyId == c.theirKeyId {
 
1058
                theirPub = c.theirCurrentDHPub
 
1059
        } else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil {
 
1060
                theirPub = c.theirLastDHPub
 
1061
        } else {
 
1062
                err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10))
 
1063
                return
 
1064
        }
 
1065
 
 
1066
        var sendPrefixByte, recvPrefixByte [1]byte
 
1067
 
 
1068
        if myPub.Cmp(theirPub) > 0 {
 
1069
                // we're the high end
 
1070
                sendPrefixByte[0], recvPrefixByte[0] = 1, 2
 
1071
        } else {
 
1072
                // we're the low end
 
1073
                sendPrefixByte[0], recvPrefixByte[0] = 2, 1
 
1074
        }
 
1075
 
 
1076
        s := new(big.Int).Exp(theirPub, myPriv, p)
 
1077
        sBytes := appendMPI(nil, s)
 
1078
 
 
1079
        h := sha1.New()
 
1080
        h.Write(sendPrefixByte[:])
 
1081
        h.Write(sBytes)
 
1082
        slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16]
 
1083
 
 
1084
        h.Reset()
 
1085
        h.Write(slot.sendAESKey)
 
1086
        slot.sendMACKey = h.Sum(slot.sendMACKey[:0])
 
1087
 
 
1088
        h.Reset()
 
1089
        h.Write(recvPrefixByte[:])
 
1090
        h.Write(sBytes)
 
1091
        slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16]
 
1092
 
 
1093
        h.Reset()
 
1094
        h.Write(slot.recvAESKey)
 
1095
        slot.recvMACKey = h.Sum(slot.recvMACKey[:0])
 
1096
 
 
1097
        slot.theirKeyId = theirKeyId
 
1098
        slot.myKeyId = myKeyId
 
1099
        slot.used = true
 
1100
 
 
1101
        zero(slot.theirLastCtr[:])
 
1102
        return
 
1103
}
 
1104
 
 
1105
func (c *Conversation) calcAKEKeys(s *big.Int) {
 
1106
        mpi := appendMPI(nil, s)
 
1107
        h := sha256.New()
 
1108
 
 
1109
        var cBytes [32]byte
 
1110
        hashWithPrefix(c.SSID[:], 0, mpi, h)
 
1111
 
 
1112
        hashWithPrefix(cBytes[:], 1, mpi, h)
 
1113
        copy(c.revealKeys.c[:], cBytes[:16])
 
1114
        copy(c.sigKeys.c[:], cBytes[16:])
 
1115
 
 
1116
        hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h)
 
1117
        hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h)
 
1118
        hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h)
 
1119
        hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h)
 
1120
}
 
1121
 
 
1122
func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) {
 
1123
        h.Reset()
 
1124
        var p [1]byte
 
1125
        p[0] = prefix
 
1126
        h.Write(p[:])
 
1127
        h.Write(in)
 
1128
        if len(out) == h.Size() {
 
1129
                h.Sum(out[:0])
 
1130
        } else {
 
1131
                digest := h.Sum(nil)
 
1132
                copy(out, digest)
 
1133
        }
 
1134
}
 
1135
 
 
1136
func (c *Conversation) encode(msg []byte) [][]byte {
 
1137
        b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1)
 
1138
        base64.StdEncoding.Encode(b64[len(msgPrefix):], msg)
 
1139
        copy(b64, msgPrefix)
 
1140
        b64[len(b64)-1] = '.'
 
1141
 
 
1142
        if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize {
 
1143
                // We can encode this in a single fragment.
 
1144
                return [][]byte{b64}
 
1145
        }
 
1146
 
 
1147
        // We have to fragment this message.
 
1148
        var ret [][]byte
 
1149
        bytesPerFragment := c.FragmentSize - minFragmentSize
 
1150
        numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment
 
1151
 
 
1152
        for i := 0; i < numFragments; i++ {
 
1153
                frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",")
 
1154
                todo := bytesPerFragment
 
1155
                if todo > len(b64) {
 
1156
                        todo = len(b64)
 
1157
                }
 
1158
                frag = append(frag, b64[:todo]...)
 
1159
                b64 = b64[todo:]
 
1160
                frag = append(frag, ',')
 
1161
                ret = append(ret, frag)
 
1162
        }
 
1163
 
 
1164
        return ret
 
1165
}
 
1166
 
 
1167
type PublicKey struct {
 
1168
        dsa.PublicKey
 
1169
}
 
1170
 
 
1171
func (pk *PublicKey) Parse(in []byte) ([]byte, bool) {
 
1172
        var ok bool
 
1173
        var pubKeyType uint16
 
1174
 
 
1175
        if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 {
 
1176
                return nil, false
 
1177
        }
 
1178
        if pk.P, in, ok = getMPI(in); !ok {
 
1179
                return nil, false
 
1180
        }
 
1181
        if pk.Q, in, ok = getMPI(in); !ok {
 
1182
                return nil, false
 
1183
        }
 
1184
        if pk.G, in, ok = getMPI(in); !ok {
 
1185
                return nil, false
 
1186
        }
 
1187
        if pk.Y, in, ok = getMPI(in); !ok {
 
1188
                return nil, false
 
1189
        }
 
1190
 
 
1191
        return in, true
 
1192
}
 
1193
 
 
1194
func (pk *PublicKey) Serialize(in []byte) []byte {
 
1195
        in = appendU16(in, 0)
 
1196
        in = appendMPI(in, pk.P)
 
1197
        in = appendMPI(in, pk.Q)
 
1198
        in = appendMPI(in, pk.G)
 
1199
        in = appendMPI(in, pk.Y)
 
1200
        return in
 
1201
}
 
1202
 
 
1203
// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey.
 
1204
func (pk *PublicKey) Fingerprint() []byte {
 
1205
        b := pk.Serialize(nil)
 
1206
        h := sha1.New()
 
1207
        h.Write(b[2:])
 
1208
        return h.Sum(nil)
 
1209
}
 
1210
 
 
1211
func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) {
 
1212
        if len(sig) != 2*dsaSubgroupBytes {
 
1213
                return nil, false
 
1214
        }
 
1215
        r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes])
 
1216
        s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:])
 
1217
        ok := dsa.Verify(&pk.PublicKey, hashed, r, s)
 
1218
        return sig[dsaSubgroupBytes*2:], ok
 
1219
}
 
1220
 
 
1221
type PrivateKey struct {
 
1222
        PublicKey
 
1223
        dsa.PrivateKey
 
1224
}
 
1225
 
 
1226
func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte {
 
1227
        r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed)
 
1228
        if err != nil {
 
1229
                panic(err.Error())
 
1230
        }
 
1231
        rBytes := r.Bytes()
 
1232
        sBytes := s.Bytes()
 
1233
        if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes {
 
1234
                panic("DSA signature too large")
 
1235
        }
 
1236
 
 
1237
        out := make([]byte, 2*dsaSubgroupBytes)
 
1238
        copy(out[dsaSubgroupBytes-len(rBytes):], rBytes)
 
1239
        copy(out[len(out)-len(sBytes):], sBytes)
 
1240
        return out
 
1241
}
 
1242
 
 
1243
func (priv *PrivateKey) Serialize(in []byte) []byte {
 
1244
        in = priv.PublicKey.Serialize(in)
 
1245
        in = appendMPI(in, priv.PrivateKey.X)
 
1246
        return in
 
1247
}
 
1248
 
 
1249
func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) {
 
1250
        in, ok := priv.PublicKey.Parse(in)
 
1251
        if !ok {
 
1252
                return in, ok
 
1253
        }
 
1254
        priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey
 
1255
        priv.PrivateKey.X, in, ok = getMPI(in)
 
1256
        return in, ok
 
1257
}
 
1258
 
 
1259
func (priv *PrivateKey) Generate(rand io.Reader) {
 
1260
        if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil {
 
1261
                panic(err.Error())
 
1262
        }
 
1263
        if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil {
 
1264
                panic(err.Error())
 
1265
        }
 
1266
        priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
 
1267
}
 
1268
 
 
1269
func notHex(r rune) bool {
 
1270
        if r >= '0' && r <= '9' ||
 
1271
                r >= 'a' && r <= 'f' ||
 
1272
                r >= 'A' && r <= 'F' {
 
1273
                return false
 
1274
        }
 
1275
 
 
1276
        return true
 
1277
}
 
1278
 
 
1279
// Import parses the contents of a libotr private key file.
 
1280
func (priv *PrivateKey) Import(in []byte) bool {
 
1281
        mpiStart := []byte(" #")
 
1282
 
 
1283
        mpis := make([]*big.Int, 5)
 
1284
 
 
1285
        for i := 0; i < len(mpis); i++ {
 
1286
                start := bytes.Index(in, mpiStart)
 
1287
                if start == -1 {
 
1288
                        return false
 
1289
                }
 
1290
                in = in[start+len(mpiStart):]
 
1291
                end := bytes.IndexFunc(in, notHex)
 
1292
                if end == -1 {
 
1293
                        return false
 
1294
                }
 
1295
                hexBytes := in[:end]
 
1296
                in = in[end:]
 
1297
 
 
1298
                if len(hexBytes)&1 != 0 {
 
1299
                        return false
 
1300
                }
 
1301
 
 
1302
                mpiBytes := make([]byte, len(hexBytes)/2)
 
1303
                if _, err := hex.Decode(mpiBytes, hexBytes); err != nil {
 
1304
                        return false
 
1305
                }
 
1306
 
 
1307
                mpis[i] = new(big.Int).SetBytes(mpiBytes)
 
1308
        }
 
1309
 
 
1310
        priv.PrivateKey.P = mpis[0]
 
1311
        priv.PrivateKey.Q = mpis[1]
 
1312
        priv.PrivateKey.G = mpis[2]
 
1313
        priv.PrivateKey.Y = mpis[3]
 
1314
        priv.PrivateKey.X = mpis[4]
 
1315
        priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
 
1316
 
 
1317
        a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P)
 
1318
        return a.Cmp(priv.PrivateKey.Y) == 0
 
1319
}
 
1320
 
 
1321
func getU8(in []byte) (uint8, []byte, bool) {
 
1322
        if len(in) < 1 {
 
1323
                return 0, in, false
 
1324
        }
 
1325
        return in[0], in[1:], true
 
1326
}
 
1327
 
 
1328
func getU16(in []byte) (uint16, []byte, bool) {
 
1329
        if len(in) < 2 {
 
1330
                return 0, in, false
 
1331
        }
 
1332
        r := uint16(in[0])<<8 | uint16(in[1])
 
1333
        return r, in[2:], true
 
1334
}
 
1335
 
 
1336
func getU32(in []byte) (uint32, []byte, bool) {
 
1337
        if len(in) < 4 {
 
1338
                return 0, in, false
 
1339
        }
 
1340
        r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
 
1341
        return r, in[4:], true
 
1342
}
 
1343
 
 
1344
func getMPI(in []byte) (*big.Int, []byte, bool) {
 
1345
        l, in, ok := getU32(in)
 
1346
        if !ok || uint32(len(in)) < l {
 
1347
                return nil, in, false
 
1348
        }
 
1349
        r := new(big.Int).SetBytes(in[:l])
 
1350
        return r, in[l:], true
 
1351
}
 
1352
 
 
1353
func getData(in []byte) ([]byte, []byte, bool) {
 
1354
        l, in, ok := getU32(in)
 
1355
        if !ok || uint32(len(in)) < l {
 
1356
                return nil, in, false
 
1357
        }
 
1358
        return in[:l], in[l:], true
 
1359
}
 
1360
 
 
1361
func getNBytes(in []byte, n int) ([]byte, []byte, bool) {
 
1362
        if len(in) < n {
 
1363
                return nil, in, false
 
1364
        }
 
1365
        return in[:n], in[n:], true
 
1366
}
 
1367
 
 
1368
func appendU16(out []byte, v uint16) []byte {
 
1369
        out = append(out, byte(v>>8), byte(v))
 
1370
        return out
 
1371
}
 
1372
 
 
1373
func appendU32(out []byte, v uint32) []byte {
 
1374
        out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 
1375
        return out
 
1376
}
 
1377
 
 
1378
func appendData(out, v []byte) []byte {
 
1379
        out = appendU32(out, uint32(len(v)))
 
1380
        out = append(out, v...)
 
1381
        return out
 
1382
}
 
1383
 
 
1384
func appendMPI(out []byte, v *big.Int) []byte {
 
1385
        vBytes := v.Bytes()
 
1386
        out = appendU32(out, uint32(len(vBytes)))
 
1387
        out = append(out, vBytes...)
 
1388
        return out
 
1389
}
 
1390
 
 
1391
func appendMPIs(out []byte, mpis ...*big.Int) []byte {
 
1392
        for _, mpi := range mpis {
 
1393
                out = appendMPI(out, mpi)
 
1394
        }
 
1395
        return out
 
1396
}
 
1397
 
 
1398
func zero(b []byte) {
 
1399
        for i := range b {
 
1400
                b[i] = 0
 
1401
        }
 
1402
}