Alternative TLS implementation in Go
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

203 lignes
5.0 KiB

  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package tls
  5. import (
  6. "rand"
  7. "reflect"
  8. "testing"
  9. "testing/quick"
  10. )
  11. var tests = []interface{}{
  12. &clientHelloMsg{},
  13. &serverHelloMsg{},
  14. &certificateMsg{},
  15. &certificateRequestMsg{},
  16. &certificateVerifyMsg{},
  17. &certificateStatusMsg{},
  18. &clientKeyExchangeMsg{},
  19. &finishedMsg{},
  20. &nextProtoMsg{},
  21. }
  22. type testMessage interface {
  23. marshal() []byte
  24. unmarshal([]byte) bool
  25. }
  26. func TestMarshalUnmarshal(t *testing.T) {
  27. rand := rand.New(rand.NewSource(0))
  28. for i, iface := range tests {
  29. ty := reflect.NewValue(iface).Type()
  30. for j := 0; j < 100; j++ {
  31. v, ok := quick.Value(ty, rand)
  32. if !ok {
  33. t.Errorf("#%d: failed to create value", i)
  34. break
  35. }
  36. m1 := v.Interface().(testMessage)
  37. marshaled := m1.marshal()
  38. m2 := iface.(testMessage)
  39. if !m2.unmarshal(marshaled) {
  40. t.Errorf("#%d failed to unmarshal %#v %x", i, m1, marshaled)
  41. break
  42. }
  43. m2.marshal() // to fill any marshal cache in the message
  44. if !reflect.DeepEqual(m1, m2) {
  45. t.Errorf("#%d got:%#v want:%#v %x", i, m2, m1, marshaled)
  46. break
  47. }
  48. if i >= 2 {
  49. // The first two message types (ClientHello and
  50. // ServerHello) are allowed to have parsable
  51. // prefixes because the extension data is
  52. // optional.
  53. for j := 0; j < len(marshaled); j++ {
  54. if m2.unmarshal(marshaled[0:j]) {
  55. t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1)
  56. break
  57. }
  58. }
  59. }
  60. }
  61. }
  62. }
  63. func TestFuzz(t *testing.T) {
  64. rand := rand.New(rand.NewSource(0))
  65. for _, iface := range tests {
  66. m := iface.(testMessage)
  67. for j := 0; j < 1000; j++ {
  68. len := rand.Intn(100)
  69. bytes := randomBytes(len, rand)
  70. // This just looks for crashes due to bounds errors etc.
  71. m.unmarshal(bytes)
  72. }
  73. }
  74. }
  75. func randomBytes(n int, rand *rand.Rand) []byte {
  76. r := make([]byte, n)
  77. for i := 0; i < n; i++ {
  78. r[i] = byte(rand.Int31())
  79. }
  80. return r
  81. }
  82. func randomString(n int, rand *rand.Rand) string {
  83. b := randomBytes(n, rand)
  84. return string(b)
  85. }
  86. func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  87. m := &clientHelloMsg{}
  88. m.vers = uint16(rand.Intn(65536))
  89. m.random = randomBytes(32, rand)
  90. m.sessionId = randomBytes(rand.Intn(32), rand)
  91. m.cipherSuites = make([]uint16, rand.Intn(63)+1)
  92. for i := 0; i < len(m.cipherSuites); i++ {
  93. m.cipherSuites[i] = uint16(rand.Int31())
  94. }
  95. m.compressionMethods = randomBytes(rand.Intn(63)+1, rand)
  96. if rand.Intn(10) > 5 {
  97. m.nextProtoNeg = true
  98. }
  99. if rand.Intn(10) > 5 {
  100. m.serverName = randomString(rand.Intn(255), rand)
  101. }
  102. m.ocspStapling = rand.Intn(10) > 5
  103. m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
  104. m.supportedCurves = make([]uint16, rand.Intn(5)+1)
  105. for i, _ := range m.supportedCurves {
  106. m.supportedCurves[i] = uint16(rand.Intn(30000))
  107. }
  108. return reflect.NewValue(m)
  109. }
  110. func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  111. m := &serverHelloMsg{}
  112. m.vers = uint16(rand.Intn(65536))
  113. m.random = randomBytes(32, rand)
  114. m.sessionId = randomBytes(rand.Intn(32), rand)
  115. m.cipherSuite = uint16(rand.Int31())
  116. m.compressionMethod = uint8(rand.Intn(256))
  117. if rand.Intn(10) > 5 {
  118. m.nextProtoNeg = true
  119. n := rand.Intn(10)
  120. m.nextProtos = make([]string, n)
  121. for i := 0; i < n; i++ {
  122. m.nextProtos[i] = randomString(20, rand)
  123. }
  124. }
  125. return reflect.NewValue(m)
  126. }
  127. func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  128. m := &certificateMsg{}
  129. numCerts := rand.Intn(20)
  130. m.certificates = make([][]byte, numCerts)
  131. for i := 0; i < numCerts; i++ {
  132. m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
  133. }
  134. return reflect.NewValue(m)
  135. }
  136. func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  137. m := &certificateRequestMsg{}
  138. m.certificateTypes = randomBytes(rand.Intn(5)+1, rand)
  139. numCAs := rand.Intn(100)
  140. m.certificateAuthorities = make([][]byte, numCAs)
  141. for i := 0; i < numCAs; i++ {
  142. m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
  143. }
  144. return reflect.NewValue(m)
  145. }
  146. func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  147. m := &certificateVerifyMsg{}
  148. m.signature = randomBytes(rand.Intn(15)+1, rand)
  149. return reflect.NewValue(m)
  150. }
  151. func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  152. m := &certificateStatusMsg{}
  153. if rand.Intn(10) > 5 {
  154. m.statusType = statusTypeOCSP
  155. m.response = randomBytes(rand.Intn(10)+1, rand)
  156. } else {
  157. m.statusType = 42
  158. }
  159. return reflect.NewValue(m)
  160. }
  161. func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  162. m := &clientKeyExchangeMsg{}
  163. m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
  164. return reflect.NewValue(m)
  165. }
  166. func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  167. m := &finishedMsg{}
  168. m.verifyData = randomBytes(12, rand)
  169. return reflect.NewValue(m)
  170. }
  171. func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
  172. m := &nextProtoMsg{}
  173. m.proto = randomString(rand.Intn(255), rand)
  174. return reflect.NewValue(m)
  175. }