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