messages.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright (c) Tailscale Inc & contributors
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package controlbase
  4. import "encoding/binary"
  5. const (
  6. // msgTypeInitiation frames carry a Noise IK handshake initiation message.
  7. msgTypeInitiation = 1
  8. // msgTypeResponse frames carry a Noise IK handshake response message.
  9. msgTypeResponse = 2
  10. // msgTypeError frames carry an unauthenticated human-readable
  11. // error message.
  12. //
  13. // Errors reported in this message type must be treated as public
  14. // hints only. They are not encrypted or authenticated, and so can
  15. // be seen and tampered with on the wire.
  16. msgTypeError = 3
  17. // msgTypeRecord frames carry session data bytes.
  18. msgTypeRecord = 4
  19. // headerLen is the size of the header on all messages except msgTypeInitiation.
  20. headerLen = 3
  21. // initiationHeaderLen is the size of the header on all msgTypeInitiation messages.
  22. initiationHeaderLen = 5
  23. )
  24. // initiationMessage is the protocol message sent from a client
  25. // machine to a control server.
  26. //
  27. // 2b: protocol version
  28. // 1b: message type (0x01)
  29. // 2b: payload length (96)
  30. // 5b: header (see headerLen for fields)
  31. // 32b: client ephemeral public key (cleartext)
  32. // 48b: client machine public key (encrypted)
  33. // 16b: message tag (authenticates the whole message)
  34. type initiationMessage [101]byte
  35. func mkInitiationMessage(protocolVersion uint16) initiationMessage {
  36. var ret initiationMessage
  37. binary.BigEndian.PutUint16(ret[:2], protocolVersion)
  38. ret[2] = msgTypeInitiation
  39. binary.BigEndian.PutUint16(ret[3:5], uint16(len(ret.Payload())))
  40. return ret
  41. }
  42. func (m *initiationMessage) Header() []byte { return m[:initiationHeaderLen] }
  43. func (m *initiationMessage) Payload() []byte { return m[initiationHeaderLen:] }
  44. func (m *initiationMessage) Version() uint16 { return binary.BigEndian.Uint16(m[:2]) }
  45. func (m *initiationMessage) Type() byte { return m[2] }
  46. func (m *initiationMessage) Length() int { return int(binary.BigEndian.Uint16(m[3:5])) }
  47. func (m *initiationMessage) EphemeralPub() []byte {
  48. return m[initiationHeaderLen : initiationHeaderLen+32]
  49. }
  50. func (m *initiationMessage) MachinePub() []byte {
  51. return m[initiationHeaderLen+32 : initiationHeaderLen+32+48]
  52. }
  53. func (m *initiationMessage) Tag() []byte { return m[initiationHeaderLen+32+48:] }
  54. // responseMessage is the protocol message sent from a control server
  55. // to a client machine.
  56. //
  57. // 1b: message type (0x02)
  58. // 2b: payload length (48)
  59. // 32b: control ephemeral public key (cleartext)
  60. // 16b: message tag (authenticates the whole message)
  61. type responseMessage [51]byte
  62. func mkResponseMessage() responseMessage {
  63. var ret responseMessage
  64. ret[0] = msgTypeResponse
  65. binary.BigEndian.PutUint16(ret[1:], uint16(len(ret.Payload())))
  66. return ret
  67. }
  68. func (m *responseMessage) Header() []byte { return m[:headerLen] }
  69. func (m *responseMessage) Payload() []byte { return m[headerLen:] }
  70. func (m *responseMessage) Type() byte { return m[0] }
  71. func (m *responseMessage) Length() int { return int(binary.BigEndian.Uint16(m[1:3])) }
  72. func (m *responseMessage) EphemeralPub() []byte { return m[headerLen : headerLen+32] }
  73. func (m *responseMessage) Tag() []byte { return m[headerLen+32:] }