extension.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. // Package extension implements the extension values in the ClientHello/ServerHello
  4. package extension
  5. import "encoding/binary"
  6. // TypeValue is the 2 byte value for a TLS Extension as registered in the IANA
  7. //
  8. // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
  9. type TypeValue uint16
  10. // TypeValue constants
  11. const (
  12. ServerNameTypeValue TypeValue = 0
  13. SupportedEllipticCurvesTypeValue TypeValue = 10
  14. SupportedPointFormatsTypeValue TypeValue = 11
  15. SupportedSignatureAlgorithmsTypeValue TypeValue = 13
  16. UseSRTPTypeValue TypeValue = 14
  17. ALPNTypeValue TypeValue = 16
  18. UseExtendedMasterSecretTypeValue TypeValue = 23
  19. RenegotiationInfoTypeValue TypeValue = 65281
  20. )
  21. // Extension represents a single TLS extension
  22. type Extension interface {
  23. Marshal() ([]byte, error)
  24. Unmarshal(data []byte) error
  25. TypeValue() TypeValue
  26. }
  27. // Unmarshal many extensions at once
  28. func Unmarshal(buf []byte) ([]Extension, error) {
  29. switch {
  30. case len(buf) == 0:
  31. return []Extension{}, nil
  32. case len(buf) < 2:
  33. return nil, errBufferTooSmall
  34. }
  35. declaredLen := binary.BigEndian.Uint16(buf)
  36. if len(buf)-2 != int(declaredLen) {
  37. return nil, errLengthMismatch
  38. }
  39. extensions := []Extension{}
  40. unmarshalAndAppend := func(data []byte, e Extension) error {
  41. err := e.Unmarshal(data)
  42. if err != nil {
  43. return err
  44. }
  45. extensions = append(extensions, e)
  46. return nil
  47. }
  48. for offset := 2; offset < len(buf); {
  49. if len(buf) < (offset + 2) {
  50. return nil, errBufferTooSmall
  51. }
  52. var err error
  53. switch TypeValue(binary.BigEndian.Uint16(buf[offset:])) {
  54. case ServerNameTypeValue:
  55. err = unmarshalAndAppend(buf[offset:], &ServerName{})
  56. case SupportedEllipticCurvesTypeValue:
  57. err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{})
  58. case UseSRTPTypeValue:
  59. err = unmarshalAndAppend(buf[offset:], &UseSRTP{})
  60. case ALPNTypeValue:
  61. err = unmarshalAndAppend(buf[offset:], &ALPN{})
  62. case UseExtendedMasterSecretTypeValue:
  63. err = unmarshalAndAppend(buf[offset:], &UseExtendedMasterSecret{})
  64. case RenegotiationInfoTypeValue:
  65. err = unmarshalAndAppend(buf[offset:], &RenegotiationInfo{})
  66. default:
  67. }
  68. if err != nil {
  69. return nil, err
  70. }
  71. if len(buf) < (offset + 4) {
  72. return nil, errBufferTooSmall
  73. }
  74. extensionLength := binary.BigEndian.Uint16(buf[offset+2:])
  75. offset += (4 + int(extensionLength))
  76. }
  77. return extensions, nil
  78. }
  79. // Marshal many extensions at once
  80. func Marshal(e []Extension) ([]byte, error) {
  81. extensions := []byte{}
  82. for _, e := range e {
  83. raw, err := e.Marshal()
  84. if err != nil {
  85. return nil, err
  86. }
  87. extensions = append(extensions, raw...)
  88. }
  89. out := []byte{0x00, 0x00}
  90. binary.BigEndian.PutUint16(out, uint16(len(extensions)))
  91. return append(out, extensions...), nil
  92. }