| 442 | } |
| 443 | |
| 444 | func (device *Device) CreateMessageResponse(peer *Peer) (*MessageResponse, error) { |
| 445 | handshake := &peer.handshake |
| 446 | handshake.mutex.Lock() |
| 447 | defer handshake.mutex.Unlock() |
| 448 | |
| 449 | if handshake.state != handshakeInitiationConsumed { |
| 450 | return nil, errors.New("handshake initiation must be consumed first") |
| 451 | } |
| 452 | |
| 453 | // assign index |
| 454 | |
| 455 | var err error |
| 456 | device.indexTable.Delete(handshake.localIndex) |
| 457 | handshake.localIndex, err = device.indexTable.NewIndexForHandshake(peer, handshake) |
| 458 | if err != nil { |
| 459 | return nil, err |
| 460 | } |
| 461 | |
| 462 | var msg MessageResponse |
| 463 | msg.Type = MessageResponseType |
| 464 | msg.Sender = handshake.localIndex |
| 465 | msg.Receiver = handshake.remoteIndex |
| 466 | |
| 467 | // create ephemeral key |
| 468 | |
| 469 | handshake.localEphemeral, err = newPrivateKey() |
| 470 | if err != nil { |
| 471 | return nil, err |
| 472 | } |
| 473 | msg.Ephemeral = handshake.localEphemeral.publicKey() |
| 474 | handshake.mixHash(msg.Ephemeral[:]) |
| 475 | handshake.mixKey(msg.Ephemeral[:]) |
| 476 | |
| 477 | ss, err := handshake.localEphemeral.sharedSecret(handshake.remoteEphemeral) |
| 478 | if err != nil { |
| 479 | return nil, err |
| 480 | } |
| 481 | handshake.mixKey(ss[:]) |
| 482 | ss, err = handshake.localEphemeral.sharedSecret(handshake.remoteStatic) |
| 483 | if err != nil { |
| 484 | return nil, err |
| 485 | } |
| 486 | handshake.mixKey(ss[:]) |
| 487 | |
| 488 | // add preshared key |
| 489 | |
| 490 | var tau [blake2s.Size]byte |
| 491 | var key [chacha20poly1305.KeySize]byte |
| 492 | |
| 493 | KDF3( |
| 494 | &handshake.chainKey, |
| 495 | &tau, |
| 496 | &key, |
| 497 | handshake.chainKey[:], |
| 498 | handshake.presharedKey[:], |
| 499 | ) |
| 500 | |
| 501 | handshake.mixHash(tau[:]) |