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