handshake.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. // Package handshake provides the DTLS wire protocol for handshakes
  4. package handshake
  5. import (
  6. "github.com/pion/dtls/v2/internal/ciphersuite/types"
  7. "github.com/pion/dtls/v2/internal/util"
  8. "github.com/pion/dtls/v2/pkg/protocol"
  9. )
  10. // Type is the unique identifier for each handshake message
  11. // https://tools.ietf.org/html/rfc5246#section-7.4
  12. type Type uint8
  13. // Types of DTLS Handshake messages we know about
  14. const (
  15. TypeHelloRequest Type = 0
  16. TypeClientHello Type = 1
  17. TypeServerHello Type = 2
  18. TypeHelloVerifyRequest Type = 3
  19. TypeCertificate Type = 11
  20. TypeServerKeyExchange Type = 12
  21. TypeCertificateRequest Type = 13
  22. TypeServerHelloDone Type = 14
  23. TypeCertificateVerify Type = 15
  24. TypeClientKeyExchange Type = 16
  25. TypeFinished Type = 20
  26. )
  27. // String returns the string representation of this type
  28. func (t Type) String() string {
  29. switch t {
  30. case TypeHelloRequest:
  31. return "HelloRequest"
  32. case TypeClientHello:
  33. return "ClientHello"
  34. case TypeServerHello:
  35. return "ServerHello"
  36. case TypeHelloVerifyRequest:
  37. return "HelloVerifyRequest"
  38. case TypeCertificate:
  39. return "TypeCertificate"
  40. case TypeServerKeyExchange:
  41. return "ServerKeyExchange"
  42. case TypeCertificateRequest:
  43. return "CertificateRequest"
  44. case TypeServerHelloDone:
  45. return "ServerHelloDone"
  46. case TypeCertificateVerify:
  47. return "CertificateVerify"
  48. case TypeClientKeyExchange:
  49. return "ClientKeyExchange"
  50. case TypeFinished:
  51. return "Finished"
  52. }
  53. return ""
  54. }
  55. // Message is the body of a Handshake datagram
  56. type Message interface {
  57. Marshal() ([]byte, error)
  58. Unmarshal(data []byte) error
  59. Type() Type
  60. }
  61. // Handshake protocol is responsible for selecting a cipher spec and
  62. // generating a master secret, which together comprise the primary
  63. // cryptographic parameters associated with a secure session. The
  64. // handshake protocol can also optionally authenticate parties who have
  65. // certificates signed by a trusted certificate authority.
  66. // https://tools.ietf.org/html/rfc5246#section-7.3
  67. type Handshake struct {
  68. Header Header
  69. Message Message
  70. KeyExchangeAlgorithm types.KeyExchangeAlgorithm
  71. }
  72. // ContentType returns what kind of content this message is carying
  73. func (h Handshake) ContentType() protocol.ContentType {
  74. return protocol.ContentTypeHandshake
  75. }
  76. // Marshal encodes a handshake into a binary message
  77. func (h *Handshake) Marshal() ([]byte, error) {
  78. if h.Message == nil {
  79. return nil, errHandshakeMessageUnset
  80. } else if h.Header.FragmentOffset != 0 {
  81. return nil, errUnableToMarshalFragmented
  82. }
  83. msg, err := h.Message.Marshal()
  84. if err != nil {
  85. return nil, err
  86. }
  87. h.Header.Length = uint32(len(msg))
  88. h.Header.FragmentLength = h.Header.Length
  89. h.Header.Type = h.Message.Type()
  90. header, err := h.Header.Marshal()
  91. if err != nil {
  92. return nil, err
  93. }
  94. return append(header, msg...), nil
  95. }
  96. // Unmarshal decodes a handshake from a binary message
  97. func (h *Handshake) Unmarshal(data []byte) error {
  98. if err := h.Header.Unmarshal(data); err != nil {
  99. return err
  100. }
  101. reportedLen := util.BigEndianUint24(data[1:])
  102. if uint32(len(data)-HeaderLength) != reportedLen {
  103. return errLengthMismatch
  104. } else if reportedLen != h.Header.FragmentLength {
  105. return errLengthMismatch
  106. }
  107. switch Type(data[0]) {
  108. case TypeHelloRequest:
  109. return errNotImplemented
  110. case TypeClientHello:
  111. h.Message = &MessageClientHello{}
  112. case TypeHelloVerifyRequest:
  113. h.Message = &MessageHelloVerifyRequest{}
  114. case TypeServerHello:
  115. h.Message = &MessageServerHello{}
  116. case TypeCertificate:
  117. h.Message = &MessageCertificate{}
  118. case TypeServerKeyExchange:
  119. h.Message = &MessageServerKeyExchange{KeyExchangeAlgorithm: h.KeyExchangeAlgorithm}
  120. case TypeCertificateRequest:
  121. h.Message = &MessageCertificateRequest{}
  122. case TypeServerHelloDone:
  123. h.Message = &MessageServerHelloDone{}
  124. case TypeClientKeyExchange:
  125. h.Message = &MessageClientKeyExchange{KeyExchangeAlgorithm: h.KeyExchangeAlgorithm}
  126. case TypeFinished:
  127. h.Message = &MessageFinished{}
  128. case TypeCertificateVerify:
  129. h.Message = &MessageCertificateVerify{}
  130. default:
  131. return errNotImplemented
  132. }
  133. return h.Message.Unmarshal(data[HeaderLength:])
  134. }