blob: 42b3a6552e5e67d6647afa4359c1c245f38d7076 [file] [log] [blame]
David Benjamin83c0bc92014-08-04 01:23:53 -04001// Copyright 2014 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
5// DTLS implementation.
6//
7// NOTE: This is a not even a remotely production-quality DTLS
8// implementation. It is the bare minimum necessary to be able to
9// achieve coverage on BoringSSL's implementation. Of note is that
10// this implementation assumes the underlying net.PacketConn is not
11// only reliable but also ordered. BoringSSL will be expected to deal
12// with simulated loss, but there is no point in forcing the test
13// driver to.
14
Adam Langleydc7e9c42015-09-29 15:21:04 -070015package runner
David Benjamin83c0bc92014-08-04 01:23:53 -040016
17import (
18 "bytes"
David Benjamin83c0bc92014-08-04 01:23:53 -040019 "errors"
20 "fmt"
21 "io"
David Benjaminb3774b92015-01-31 17:16:01 -050022 "math/rand"
David Benjamin83c0bc92014-08-04 01:23:53 -040023 "net"
24)
25
David Benjaminb1dd8cd2016-09-26 19:20:48 -040026func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
David Benjamin83c0bc92014-08-04 01:23:53 -040027 if isDTLS {
David Benjaminb1dd8cd2016-09-26 19:20:48 -040028 switch vers {
Steven Valdezc94998a2017-06-20 10:55:02 -040029 case VersionDTLS12:
David Benjaminb1dd8cd2016-09-26 19:20:48 -040030 return VersionTLS12, true
Steven Valdezc94998a2017-06-20 10:55:02 -040031 case VersionDTLS10:
David Benjaminb1dd8cd2016-09-26 19:20:48 -040032 return VersionTLS10, true
33 }
34 } else {
35 switch vers {
Steven Valdezfdd10992016-09-15 16:27:05 -040036 case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
David Benjaminb1dd8cd2016-09-26 19:20:48 -040037 return vers, true
Steven Valdezdbe01582017-07-14 10:39:28 -040038 case tls13DraftVersion, tls13ExperimentVersion, tls13RecordTypeExperimentVersion:
Steven Valdezfdd10992016-09-15 16:27:05 -040039 return VersionTLS13, true
David Benjaminb1dd8cd2016-09-26 19:20:48 -040040 }
David Benjamin83c0bc92014-08-04 01:23:53 -040041 }
David Benjaminb1dd8cd2016-09-26 19:20:48 -040042
43 return 0, false
David Benjamin83c0bc92014-08-04 01:23:53 -040044}
45
46func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
47 recordHeaderLen := dtlsRecordHeaderLen
48
49 if c.rawInput == nil {
50 c.rawInput = c.in.newBlock()
51 }
52 b := c.rawInput
53
54 // Read a new packet only if the current one is empty.
David Benjamin30152fd2016-05-05 20:45:48 -040055 var newPacket bool
David Benjamin83c0bc92014-08-04 01:23:53 -040056 if len(b.data) == 0 {
57 // Pick some absurdly large buffer size.
58 b.resize(maxCiphertext + recordHeaderLen)
59 n, err := c.conn.Read(c.rawInput.data)
60 if err != nil {
61 return 0, nil, err
62 }
David Benjamin13be1de2015-01-11 16:29:36 -050063 if c.config.Bugs.MaxPacketLength != 0 && n > c.config.Bugs.MaxPacketLength {
64 return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length")
65 }
David Benjamin83c0bc92014-08-04 01:23:53 -040066 c.rawInput.resize(n)
David Benjamin30152fd2016-05-05 20:45:48 -040067 newPacket = true
David Benjamin83c0bc92014-08-04 01:23:53 -040068 }
69
70 // Read out one record.
71 //
72 // A real DTLS implementation should be tolerant of errors,
73 // but this is test code. We should not be tolerant of our
74 // peer sending garbage.
75 if len(b.data) < recordHeaderLen {
76 return 0, nil, errors.New("dtls: failed to read record header")
77 }
78 typ := recordType(b.data[0])
David Benjaminb1dd8cd2016-09-26 19:20:48 -040079 vers := uint16(b.data[1])<<8 | uint16(b.data[2])
David Benjaminbde00392016-06-21 12:19:28 -040080 // Alerts sent near version negotiation do not have a well-defined
81 // record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer
82 // version is irrelevant.)
83 if typ != recordTypeAlert {
84 if c.haveVers {
Steven Valdezc94998a2017-06-20 10:55:02 -040085 if vers != c.wireVersion {
David Benjaminbde00392016-06-21 12:19:28 -040086 c.sendAlert(alertProtocolVersion)
Steven Valdezc94998a2017-06-20 10:55:02 -040087 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.wireVersion))
David Benjaminbde00392016-06-21 12:19:28 -040088 }
89 } else {
90 // Pre-version-negotiation alerts may be sent with any version.
91 if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
92 c.sendAlert(alertProtocolVersion)
93 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect))
94 }
David Benjamin1e29a6b2014-12-10 02:27:24 -050095 }
David Benjamin83c0bc92014-08-04 01:23:53 -040096 }
David Benjamin13e81fc2015-11-02 17:16:13 -050097 epoch := b.data[3:5]
98 seq := b.data[5:11]
99 // For test purposes, require the sequence number be monotonically
100 // increasing, so c.in includes the minimum next sequence number. Gaps
101 // may occur if packets failed to be sent out. A real implementation
102 // would maintain a replay window and such.
103 if !bytes.Equal(epoch, c.in.seq[:2]) {
104 c.sendAlert(alertIllegalParameter)
105 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad epoch"))
106 }
107 if bytes.Compare(seq, c.in.seq[2:]) < 0 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400108 c.sendAlert(alertIllegalParameter)
109 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad sequence number"))
110 }
David Benjamin13e81fc2015-11-02 17:16:13 -0500111 copy(c.in.seq[2:], seq)
David Benjamin83c0bc92014-08-04 01:23:53 -0400112 n := int(b.data[11])<<8 | int(b.data[12])
113 if n > maxCiphertext || len(b.data) < recordHeaderLen+n {
114 c.sendAlert(alertRecordOverflow)
115 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: oversized record received with length %d", n))
116 }
117
118 // Process message.
119 b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
David Benjaminff26f092016-07-01 16:13:42 -0400120 ok, off, _, alertValue := c.in.decrypt(b)
David Benjamin83c0bc92014-08-04 01:23:53 -0400121 if !ok {
David Benjaminff26f092016-07-01 16:13:42 -0400122 // A real DTLS implementation would silently ignore bad records,
123 // but we want to notice errors from the implementation under
124 // test.
125 return 0, nil, c.in.setErrorLocked(c.sendAlert(alertValue))
David Benjamin83c0bc92014-08-04 01:23:53 -0400126 }
127 b.off = off
David Benjamin30152fd2016-05-05 20:45:48 -0400128
David Benjaminff26f092016-07-01 16:13:42 -0400129 // TODO(nharper): Once DTLS 1.3 is defined, handle the extra
130 // parameter from decrypt.
131
David Benjamin30152fd2016-05-05 20:45:48 -0400132 // Require that ChangeCipherSpec always share a packet with either the
133 // previous or next handshake message.
134 if newPacket && typ == recordTypeChangeCipherSpec && c.rawInput == nil {
135 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: ChangeCipherSpec not packed together with Finished"))
136 }
137
David Benjamin83c0bc92014-08-04 01:23:53 -0400138 return typ, b, nil
139}
140
David Benjamin75381222015-03-02 19:30:30 -0500141func (c *Conn) makeFragment(header, data []byte, fragOffset, fragLen int) []byte {
142 fragment := make([]byte, 0, 12+fragLen)
143 fragment = append(fragment, header...)
144 fragment = append(fragment, byte(c.sendHandshakeSeq>>8), byte(c.sendHandshakeSeq))
145 fragment = append(fragment, byte(fragOffset>>16), byte(fragOffset>>8), byte(fragOffset))
146 fragment = append(fragment, byte(fragLen>>16), byte(fragLen>>8), byte(fragLen))
147 fragment = append(fragment, data[fragOffset:fragOffset+fragLen]...)
148 return fragment
149}
150
David Benjamin83c0bc92014-08-04 01:23:53 -0400151func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) {
David Benjamind660b572015-01-31 15:13:21 -0500152 if typ != recordTypeHandshake {
David Benjaminb0c761e2017-06-25 22:42:55 -0400153 reorder := typ == recordTypeChangeCipherSpec && c.config.Bugs.ReorderChangeCipherSpec
154
155 // Flush pending handshake messages before writing a new record.
156 if !reorder {
157 err = c.dtlsFlushHandshake()
158 if err != nil {
159 return
160 }
161 }
162
David Benjamind660b572015-01-31 15:13:21 -0500163 // Only handshake messages are fragmented.
David Benjamin8144f992016-06-22 17:05:13 -0400164 n, err = c.dtlsWriteRawRecord(typ, data)
165 if err != nil {
166 return
167 }
168
David Benjaminb0c761e2017-06-25 22:42:55 -0400169 if reorder {
170 err = c.dtlsFlushHandshake()
171 if err != nil {
172 return
173 }
174 }
175
David Benjamin8144f992016-06-22 17:05:13 -0400176 if typ == recordTypeChangeCipherSpec {
177 err = c.out.changeCipherSpec(c.config)
178 if err != nil {
David Benjamina8181342017-07-07 18:10:57 -0400179 return n, c.sendAlertLocked(alertLevelError, err.(alert))
David Benjamin8144f992016-06-22 17:05:13 -0400180 }
181 }
182 return
183 }
184
185 if c.out.cipher == nil && c.config.Bugs.StrayChangeCipherSpec {
186 _, err = c.dtlsWriteRawRecord(recordTypeChangeCipherSpec, []byte{1})
187 if err != nil {
188 return
189 }
David Benjamind660b572015-01-31 15:13:21 -0500190 }
191
192 maxLen := c.config.Bugs.MaxHandshakeRecordLength
193 if maxLen <= 0 {
194 maxLen = 1024
195 }
196
197 // Handshake messages have to be modified to include fragment
198 // offset and length and with the header replicated. Save the
199 // TLS header here.
200 //
201 // TODO(davidben): This assumes that data contains exactly one
202 // handshake message. This is incompatible with
203 // FragmentAcrossChangeCipherSpec. (Which is unfortunate
204 // because OpenSSL's DTLS implementation will probably accept
205 // such fragmentation and could do with a fix + tests.)
David Benjamind660b572015-01-31 15:13:21 -0500206 header := data[:4]
207 data = data[4:]
208
David Benjamina4e6d482015-03-02 19:10:53 -0500209 isFinished := header[0] == typeFinished
210
David Benjamin75381222015-03-02 19:30:30 -0500211 if c.config.Bugs.SendEmptyFragments {
212 fragment := c.makeFragment(header, data, 0, 0)
213 c.pendingFragments = append(c.pendingFragments, fragment)
214 }
215
David Benjamind660b572015-01-31 15:13:21 -0500216 firstRun := true
David Benjamin75381222015-03-02 19:30:30 -0500217 fragOffset := 0
218 for firstRun || fragOffset < len(data) {
David Benjamind660b572015-01-31 15:13:21 -0500219 firstRun = false
David Benjamin75381222015-03-02 19:30:30 -0500220 fragLen := len(data) - fragOffset
221 if fragLen > maxLen {
222 fragLen = maxLen
David Benjamind660b572015-01-31 15:13:21 -0500223 }
224
David Benjamin75381222015-03-02 19:30:30 -0500225 fragment := c.makeFragment(header, data, fragOffset, fragLen)
226 if c.config.Bugs.FragmentMessageTypeMismatch && fragOffset > 0 {
227 fragment[0]++
228 }
229 if c.config.Bugs.FragmentMessageLengthMismatch && fragOffset > 0 {
230 fragment[3]++
231 }
David Benjamind660b572015-01-31 15:13:21 -0500232
David Benjaminb3774b92015-01-31 17:16:01 -0500233 // Buffer the fragment for later. They will be sent (and
234 // reordered) on flush.
235 c.pendingFragments = append(c.pendingFragments, fragment)
David Benjamina4e6d482015-03-02 19:10:53 -0500236 if c.config.Bugs.ReorderHandshakeFragments {
237 // Don't duplicate Finished to avoid the peer
238 // interpreting it as a retransmit request.
239 if !isFinished {
240 c.pendingFragments = append(c.pendingFragments, fragment)
241 }
David Benjaminb3774b92015-01-31 17:16:01 -0500242
David Benjamin75381222015-03-02 19:30:30 -0500243 if fragLen > (maxLen+1)/2 {
David Benjamina4e6d482015-03-02 19:10:53 -0500244 // Overlap each fragment by half.
David Benjamin75381222015-03-02 19:30:30 -0500245 fragLen = (maxLen + 1) / 2
David Benjamina4e6d482015-03-02 19:10:53 -0500246 }
David Benjamind660b572015-01-31 15:13:21 -0500247 }
David Benjamin75381222015-03-02 19:30:30 -0500248 fragOffset += fragLen
249 n += fragLen
250 }
251 if !isFinished && c.config.Bugs.MixCompleteMessageWithFragments {
252 fragment := c.makeFragment(header, data, 0, len(data))
253 c.pendingFragments = append(c.pendingFragments, fragment)
David Benjamind660b572015-01-31 15:13:21 -0500254 }
255
256 // Increment the handshake sequence number for the next
257 // handshake message.
258 c.sendHandshakeSeq++
259 return
260}
261
David Benjamina4e6d482015-03-02 19:10:53 -0500262func (c *Conn) dtlsFlushHandshake() error {
David Benjaminbd15a8e2015-05-29 18:48:16 -0400263 // This is a test-only DTLS implementation, so there is no need to
264 // retain |c.pendingFragments| for a future retransmit.
David Benjaminafbc63f2015-02-01 02:33:59 -0500265 var fragments [][]byte
David Benjaminb3774b92015-01-31 17:16:01 -0500266 fragments, c.pendingFragments = c.pendingFragments, fragments
267
268 if c.config.Bugs.ReorderHandshakeFragments {
David Benjaminb3774b92015-01-31 17:16:01 -0500269 perm := rand.New(rand.NewSource(0)).Perm(len(fragments))
270 tmp := make([][]byte, len(fragments))
271 for i := range tmp {
272 tmp[i] = fragments[perm[i]]
273 }
274 fragments = tmp
David Benjamin61672812016-07-14 23:10:43 -0400275 } else if c.config.Bugs.ReverseHandshakeFragments {
276 tmp := make([][]byte, len(fragments))
277 for i := range tmp {
278 tmp[i] = fragments[len(fragments)-i-1]
279 }
280 fragments = tmp
David Benjaminb3774b92015-01-31 17:16:01 -0500281 }
282
David Benjaminbd15a8e2015-05-29 18:48:16 -0400283 maxRecordLen := c.config.Bugs.PackHandshakeFragments
284 maxPacketLen := c.config.Bugs.PackHandshakeRecords
285
286 // Pack handshake fragments into records.
287 var records [][]byte
David Benjaminb3774b92015-01-31 17:16:01 -0500288 for _, fragment := range fragments {
David Benjamin11fc66a2015-06-16 11:40:24 -0400289 if n := c.config.Bugs.SplitFragments; n > 0 {
290 if len(fragment) > n {
291 records = append(records, fragment[:n])
292 records = append(records, fragment[n:])
David Benjaminbd15a8e2015-05-29 18:48:16 -0400293 } else {
294 records = append(records, fragment)
David Benjamin75381222015-03-02 19:30:30 -0500295 }
David Benjaminbd15a8e2015-05-29 18:48:16 -0400296 } else if i := len(records) - 1; len(records) > 0 && len(records[i])+len(fragment) <= maxRecordLen {
297 records[i] = append(records[i], fragment...)
298 } else {
299 // The fragment will be appended to, so copy it.
300 records = append(records, append([]byte{}, fragment...))
301 }
302 }
303
304 // Format them into packets.
305 var packets [][]byte
306 for _, record := range records {
307 b, err := c.dtlsSealRecord(recordTypeHandshake, record)
308 if err != nil {
309 return err
David Benjamin75381222015-03-02 19:30:30 -0500310 }
311
David Benjaminbd15a8e2015-05-29 18:48:16 -0400312 if i := len(packets) - 1; len(packets) > 0 && len(packets[i])+len(b.data) <= maxPacketLen {
313 packets[i] = append(packets[i], b.data...)
314 } else {
315 // The sealed record will be appended to and reused by
316 // |c.out|, so copy it.
317 packets = append(packets, append([]byte{}, b.data...))
318 }
319 c.out.freeBlock(b)
320 }
321
322 // Send all the packets.
323 for _, packet := range packets {
324 if _, err := c.conn.Write(packet); err != nil {
David Benjaminb3774b92015-01-31 17:16:01 -0500325 return err
326 }
327 }
328 return nil
329}
330
David Benjaminbd15a8e2015-05-29 18:48:16 -0400331// dtlsSealRecord seals a record into a block from |c.out|'s pool.
332func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error) {
David Benjamin83c0bc92014-08-04 01:23:53 -0400333 recordHeaderLen := dtlsRecordHeaderLen
334 maxLen := c.config.Bugs.MaxHandshakeRecordLength
335 if maxLen <= 0 {
336 maxLen = 1024
337 }
338
David Benjaminbd15a8e2015-05-29 18:48:16 -0400339 b = c.out.newBlock()
David Benjamin83c0bc92014-08-04 01:23:53 -0400340
David Benjamind660b572015-01-31 15:13:21 -0500341 explicitIVLen := 0
342 explicitIVIsSeq := false
343
344 if cbc, ok := c.out.cipher.(cbcMode); ok {
345 // Block cipher modes have an explicit IV.
346 explicitIVLen = cbc.BlockSize()
David Benjamine9a80ff2015-04-07 00:46:46 -0400347 } else if aead, ok := c.out.cipher.(*tlsAead); ok {
348 if aead.explicitNonce {
349 explicitIVLen = 8
350 // The AES-GCM construction in TLS has an explicit nonce so that
351 // the nonce can be random. However, the nonce is only 8 bytes
352 // which is too small for a secure, random nonce. Therefore we
353 // use the sequence number as the nonce.
354 explicitIVIsSeq = true
355 }
David Benjamin7a4aaa42016-09-20 17:58:14 -0400356 } else if _, ok := c.out.cipher.(nullCipher); !ok && c.out.cipher != nil {
David Benjamind660b572015-01-31 15:13:21 -0500357 panic("Unknown cipher")
David Benjamin83c0bc92014-08-04 01:23:53 -0400358 }
David Benjamind660b572015-01-31 15:13:21 -0500359 b.resize(recordHeaderLen + explicitIVLen + len(data))
Nick Harper1fd39d82016-06-14 18:14:35 -0700360 // TODO(nharper): DTLS 1.3 will likely need to set this to
361 // recordTypeApplicationData if c.out.cipher != nil.
David Benjamind660b572015-01-31 15:13:21 -0500362 b.data[0] = byte(typ)
Steven Valdezc94998a2017-06-20 10:55:02 -0400363 vers := c.wireVersion
David Benjamind660b572015-01-31 15:13:21 -0500364 if vers == 0 {
365 // Some TLS servers fail if the record version is greater than
366 // TLS 1.0 for the initial ClientHello.
Steven Valdezc94998a2017-06-20 10:55:02 -0400367 if c.isDTLS {
368 vers = VersionDTLS10
369 } else {
370 vers = VersionTLS10
371 }
David Benjamind660b572015-01-31 15:13:21 -0500372 }
David Benjamind660b572015-01-31 15:13:21 -0500373 b.data[1] = byte(vers >> 8)
374 b.data[2] = byte(vers)
375 // DTLS records include an explicit sequence number.
David Benjamin8e6db492015-07-25 18:29:23 -0400376 copy(b.data[3:11], c.out.outSeq[0:])
David Benjamind660b572015-01-31 15:13:21 -0500377 b.data[11] = byte(len(data) >> 8)
378 b.data[12] = byte(len(data))
379 if explicitIVLen > 0 {
380 explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
381 if explicitIVIsSeq {
David Benjamin8e6db492015-07-25 18:29:23 -0400382 copy(explicitIV, c.out.outSeq[:])
David Benjamin83c0bc92014-08-04 01:23:53 -0400383 } else {
David Benjamind660b572015-01-31 15:13:21 -0500384 if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
385 return
David Benjamin83c0bc92014-08-04 01:23:53 -0400386 }
387 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400388 }
David Benjamind660b572015-01-31 15:13:21 -0500389 copy(b.data[recordHeaderLen+explicitIVLen:], data)
Nick Harper1fd39d82016-06-14 18:14:35 -0700390 c.out.encrypt(b, explicitIVLen, typ)
David Benjaminbd15a8e2015-05-29 18:48:16 -0400391 return
392}
393
394func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) {
395 b, err := c.dtlsSealRecord(typ, data)
396 if err != nil {
397 return
398 }
David Benjamind660b572015-01-31 15:13:21 -0500399
400 _, err = c.conn.Write(b.data)
401 if err != nil {
402 return
403 }
404 n = len(data)
405
David Benjamin83c0bc92014-08-04 01:23:53 -0400406 c.out.freeBlock(b)
David Benjamin83c0bc92014-08-04 01:23:53 -0400407 return
408}
409
410func (c *Conn) dtlsDoReadHandshake() ([]byte, error) {
411 // Assemble a full handshake message. For test purposes, this
David Benjamind9b091b2015-01-27 01:10:54 -0500412 // implementation assumes fragments arrive in order. It may
413 // need to be cleverer if we ever test BoringSSL's retransmit
414 // behavior.
David Benjamin83c0bc92014-08-04 01:23:53 -0400415 for len(c.handMsg) < 4+c.handMsgLen {
416 // Get a new handshake record if the previous has been
417 // exhausted.
418 if c.hand.Len() == 0 {
419 if err := c.in.err; err != nil {
420 return nil, err
421 }
422 if err := c.readRecord(recordTypeHandshake); err != nil {
423 return nil, err
424 }
425 }
426
427 // Read the next fragment. It must fit entirely within
428 // the record.
429 if c.hand.Len() < 12 {
430 return nil, errors.New("dtls: bad handshake record")
431 }
432 header := c.hand.Next(12)
433 fragN := int(header[1])<<16 | int(header[2])<<8 | int(header[3])
434 fragSeq := uint16(header[4])<<8 | uint16(header[5])
435 fragOff := int(header[6])<<16 | int(header[7])<<8 | int(header[8])
436 fragLen := int(header[9])<<16 | int(header[10])<<8 | int(header[11])
437
438 if c.hand.Len() < fragLen {
439 return nil, errors.New("dtls: fragment length too long")
440 }
441 fragment := c.hand.Next(fragLen)
442
David Benjamind9b091b2015-01-27 01:10:54 -0500443 // Check it's a fragment for the right message.
444 if fragSeq != c.recvHandshakeSeq {
445 return nil, errors.New("dtls: bad handshake sequence number")
David Benjamin83c0bc92014-08-04 01:23:53 -0400446 }
447
448 // Check that the length is consistent.
449 if c.handMsg == nil {
450 c.handMsgLen = fragN
451 if c.handMsgLen > maxHandshake {
452 return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
453 }
454 // Start with the TLS handshake header,
455 // without the DTLS bits.
456 c.handMsg = append([]byte{}, header[:4]...)
457 } else if fragN != c.handMsgLen {
458 return nil, errors.New("dtls: bad handshake length")
459 }
460
461 // Add the fragment to the pending message.
462 if 4+fragOff != len(c.handMsg) {
463 return nil, errors.New("dtls: bad fragment offset")
464 }
465 if fragOff+fragLen > c.handMsgLen {
466 return nil, errors.New("dtls: bad fragment length")
467 }
468 c.handMsg = append(c.handMsg, fragment...)
469 }
470 c.recvHandshakeSeq++
471 ret := c.handMsg
472 c.handMsg, c.handMsgLen = nil, 0
473 return ret, nil
474}
475
476// DTLSServer returns a new DTLS server side connection
477// using conn as the underlying transport.
478// The configuration config must be non-nil and must have
479// at least one certificate.
480func DTLSServer(conn net.Conn, config *Config) *Conn {
David Benjamin5e961c12014-11-07 01:48:35 -0500481 c := &Conn{config: config, isDTLS: true, conn: conn}
482 c.init()
483 return c
David Benjamin83c0bc92014-08-04 01:23:53 -0400484}
485
486// DTLSClient returns a new DTLS client side connection
487// using conn as the underlying transport.
488// The config cannot be nil: users must set either ServerHostname or
489// InsecureSkipVerify in the config.
490func DTLSClient(conn net.Conn, config *Config) *Conn {
David Benjamin5e961c12014-11-07 01:48:35 -0500491 c := &Conn{config: config, isClient: true, isDTLS: true, conn: conn}
492 c.init()
493 return c
David Benjamin83c0bc92014-08-04 01:23:53 -0400494}