1// 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 15package runner 16 17import ( 18 "bytes" 19 "errors" 20 "fmt" 21 "io" 22 "math/rand" 23 "net" 24) 25 26func versionToWire(vers uint16, isDTLS bool) uint16 { 27 if isDTLS { 28 switch vers { 29 case VersionTLS12: 30 return 0xfefd 31 case VersionTLS10: 32 return 0xfeff 33 } 34 } else { 35 switch vers { 36 case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: 37 return vers 38 case VersionTLS13: 39 return tls13DraftVersion 40 } 41 } 42 43 panic("unknown version") 44} 45 46func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) { 47 if isDTLS { 48 switch vers { 49 case 0xfefd: 50 return VersionTLS12, true 51 case 0xfeff: 52 return VersionTLS10, true 53 } 54 } else { 55 switch vers { 56 case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: 57 return vers, true 58 case tls13DraftVersion: 59 return VersionTLS13, true 60 } 61 } 62 63 return 0, false 64} 65 66func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) { 67 recordHeaderLen := dtlsRecordHeaderLen 68 69 if c.rawInput == nil { 70 c.rawInput = c.in.newBlock() 71 } 72 b := c.rawInput 73 74 // Read a new packet only if the current one is empty. 75 var newPacket bool 76 if len(b.data) == 0 { 77 // Pick some absurdly large buffer size. 78 b.resize(maxCiphertext + recordHeaderLen) 79 n, err := c.conn.Read(c.rawInput.data) 80 if err != nil { 81 return 0, nil, err 82 } 83 if c.config.Bugs.MaxPacketLength != 0 && n > c.config.Bugs.MaxPacketLength { 84 return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length") 85 } 86 c.rawInput.resize(n) 87 newPacket = true 88 } 89 90 // Read out one record. 91 // 92 // A real DTLS implementation should be tolerant of errors, 93 // but this is test code. We should not be tolerant of our 94 // peer sending garbage. 95 if len(b.data) < recordHeaderLen { 96 return 0, nil, errors.New("dtls: failed to read record header") 97 } 98 typ := recordType(b.data[0]) 99 vers := uint16(b.data[1])<<8 | uint16(b.data[2]) 100 // Alerts sent near version negotiation do not have a well-defined 101 // record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer 102 // version is irrelevant.) 103 if typ != recordTypeAlert { 104 if c.haveVers { 105 if wireVers := versionToWire(c.vers, c.isDTLS); vers != wireVers { 106 c.sendAlert(alertProtocolVersion) 107 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, wireVers)) 108 } 109 } else { 110 // Pre-version-negotiation alerts may be sent with any version. 111 if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect { 112 c.sendAlert(alertProtocolVersion) 113 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect)) 114 } 115 } 116 } 117 epoch := b.data[3:5] 118 seq := b.data[5:11] 119 // For test purposes, require the sequence number be monotonically 120 // increasing, so c.in includes the minimum next sequence number. Gaps 121 // may occur if packets failed to be sent out. A real implementation 122 // would maintain a replay window and such. 123 if !bytes.Equal(epoch, c.in.seq[:2]) { 124 c.sendAlert(alertIllegalParameter) 125 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad epoch")) 126 } 127 if bytes.Compare(seq, c.in.seq[2:]) < 0 { 128 c.sendAlert(alertIllegalParameter) 129 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad sequence number")) 130 } 131 copy(c.in.seq[2:], seq) 132 n := int(b.data[11])<<8 | int(b.data[12]) 133 if n > maxCiphertext || len(b.data) < recordHeaderLen+n { 134 c.sendAlert(alertRecordOverflow) 135 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: oversized record received with length %d", n)) 136 } 137 138 // Process message. 139 b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n) 140 ok, off, _, alertValue := c.in.decrypt(b) 141 if !ok { 142 // A real DTLS implementation would silently ignore bad records, 143 // but we want to notice errors from the implementation under 144 // test. 145 return 0, nil, c.in.setErrorLocked(c.sendAlert(alertValue)) 146 } 147 b.off = off 148 149 // TODO(nharper): Once DTLS 1.3 is defined, handle the extra 150 // parameter from decrypt. 151 152 // Require that ChangeCipherSpec always share a packet with either the 153 // previous or next handshake message. 154 if newPacket && typ == recordTypeChangeCipherSpec && c.rawInput == nil { 155 return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: ChangeCipherSpec not packed together with Finished")) 156 } 157 158 return typ, b, nil 159} 160 161func (c *Conn) makeFragment(header, data []byte, fragOffset, fragLen int) []byte { 162 fragment := make([]byte, 0, 12+fragLen) 163 fragment = append(fragment, header...) 164 fragment = append(fragment, byte(c.sendHandshakeSeq>>8), byte(c.sendHandshakeSeq)) 165 fragment = append(fragment, byte(fragOffset>>16), byte(fragOffset>>8), byte(fragOffset)) 166 fragment = append(fragment, byte(fragLen>>16), byte(fragLen>>8), byte(fragLen)) 167 fragment = append(fragment, data[fragOffset:fragOffset+fragLen]...) 168 return fragment 169} 170 171func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { 172 if typ != recordTypeHandshake { 173 // Only handshake messages are fragmented. 174 n, err = c.dtlsWriteRawRecord(typ, data) 175 if err != nil { 176 return 177 } 178 179 if typ == recordTypeChangeCipherSpec { 180 err = c.out.changeCipherSpec(c.config) 181 if err != nil { 182 // Cannot call sendAlert directly, 183 // because we already hold c.out.Mutex. 184 c.tmp[0] = alertLevelError 185 c.tmp[1] = byte(err.(alert)) 186 c.writeRecord(recordTypeAlert, c.tmp[0:2]) 187 return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) 188 } 189 } 190 return 191 } 192 193 if c.out.cipher == nil && c.config.Bugs.StrayChangeCipherSpec { 194 _, err = c.dtlsWriteRawRecord(recordTypeChangeCipherSpec, []byte{1}) 195 if err != nil { 196 return 197 } 198 } 199 200 maxLen := c.config.Bugs.MaxHandshakeRecordLength 201 if maxLen <= 0 { 202 maxLen = 1024 203 } 204 205 // Handshake messages have to be modified to include fragment 206 // offset and length and with the header replicated. Save the 207 // TLS header here. 208 // 209 // TODO(davidben): This assumes that data contains exactly one 210 // handshake message. This is incompatible with 211 // FragmentAcrossChangeCipherSpec. (Which is unfortunate 212 // because OpenSSL's DTLS implementation will probably accept 213 // such fragmentation and could do with a fix + tests.) 214 header := data[:4] 215 data = data[4:] 216 217 isFinished := header[0] == typeFinished 218 219 if c.config.Bugs.SendEmptyFragments { 220 fragment := c.makeFragment(header, data, 0, 0) 221 c.pendingFragments = append(c.pendingFragments, fragment) 222 } 223 224 firstRun := true 225 fragOffset := 0 226 for firstRun || fragOffset < len(data) { 227 firstRun = false 228 fragLen := len(data) - fragOffset 229 if fragLen > maxLen { 230 fragLen = maxLen 231 } 232 233 fragment := c.makeFragment(header, data, fragOffset, fragLen) 234 if c.config.Bugs.FragmentMessageTypeMismatch && fragOffset > 0 { 235 fragment[0]++ 236 } 237 if c.config.Bugs.FragmentMessageLengthMismatch && fragOffset > 0 { 238 fragment[3]++ 239 } 240 241 // Buffer the fragment for later. They will be sent (and 242 // reordered) on flush. 243 c.pendingFragments = append(c.pendingFragments, fragment) 244 if c.config.Bugs.ReorderHandshakeFragments { 245 // Don't duplicate Finished to avoid the peer 246 // interpreting it as a retransmit request. 247 if !isFinished { 248 c.pendingFragments = append(c.pendingFragments, fragment) 249 } 250 251 if fragLen > (maxLen+1)/2 { 252 // Overlap each fragment by half. 253 fragLen = (maxLen + 1) / 2 254 } 255 } 256 fragOffset += fragLen 257 n += fragLen 258 } 259 if !isFinished && c.config.Bugs.MixCompleteMessageWithFragments { 260 fragment := c.makeFragment(header, data, 0, len(data)) 261 c.pendingFragments = append(c.pendingFragments, fragment) 262 } 263 264 // Increment the handshake sequence number for the next 265 // handshake message. 266 c.sendHandshakeSeq++ 267 return 268} 269 270func (c *Conn) dtlsFlushHandshake() error { 271 // This is a test-only DTLS implementation, so there is no need to 272 // retain |c.pendingFragments| for a future retransmit. 273 var fragments [][]byte 274 fragments, c.pendingFragments = c.pendingFragments, fragments 275 276 if c.config.Bugs.ReorderHandshakeFragments { 277 perm := rand.New(rand.NewSource(0)).Perm(len(fragments)) 278 tmp := make([][]byte, len(fragments)) 279 for i := range tmp { 280 tmp[i] = fragments[perm[i]] 281 } 282 fragments = tmp 283 } else if c.config.Bugs.ReverseHandshakeFragments { 284 tmp := make([][]byte, len(fragments)) 285 for i := range tmp { 286 tmp[i] = fragments[len(fragments)-i-1] 287 } 288 fragments = tmp 289 } 290 291 maxRecordLen := c.config.Bugs.PackHandshakeFragments 292 maxPacketLen := c.config.Bugs.PackHandshakeRecords 293 294 // Pack handshake fragments into records. 295 var records [][]byte 296 for _, fragment := range fragments { 297 if n := c.config.Bugs.SplitFragments; n > 0 { 298 if len(fragment) > n { 299 records = append(records, fragment[:n]) 300 records = append(records, fragment[n:]) 301 } else { 302 records = append(records, fragment) 303 } 304 } else if i := len(records) - 1; len(records) > 0 && len(records[i])+len(fragment) <= maxRecordLen { 305 records[i] = append(records[i], fragment...) 306 } else { 307 // The fragment will be appended to, so copy it. 308 records = append(records, append([]byte{}, fragment...)) 309 } 310 } 311 312 // Format them into packets. 313 var packets [][]byte 314 for _, record := range records { 315 b, err := c.dtlsSealRecord(recordTypeHandshake, record) 316 if err != nil { 317 return err 318 } 319 320 if i := len(packets) - 1; len(packets) > 0 && len(packets[i])+len(b.data) <= maxPacketLen { 321 packets[i] = append(packets[i], b.data...) 322 } else { 323 // The sealed record will be appended to and reused by 324 // |c.out|, so copy it. 325 packets = append(packets, append([]byte{}, b.data...)) 326 } 327 c.out.freeBlock(b) 328 } 329 330 // Send all the packets. 331 for _, packet := range packets { 332 if _, err := c.conn.Write(packet); err != nil { 333 return err 334 } 335 } 336 return nil 337} 338 339// dtlsSealRecord seals a record into a block from |c.out|'s pool. 340func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error) { 341 recordHeaderLen := dtlsRecordHeaderLen 342 maxLen := c.config.Bugs.MaxHandshakeRecordLength 343 if maxLen <= 0 { 344 maxLen = 1024 345 } 346 347 b = c.out.newBlock() 348 349 explicitIVLen := 0 350 explicitIVIsSeq := false 351 352 if cbc, ok := c.out.cipher.(cbcMode); ok { 353 // Block cipher modes have an explicit IV. 354 explicitIVLen = cbc.BlockSize() 355 } else if aead, ok := c.out.cipher.(*tlsAead); ok { 356 if aead.explicitNonce { 357 explicitIVLen = 8 358 // The AES-GCM construction in TLS has an explicit nonce so that 359 // the nonce can be random. However, the nonce is only 8 bytes 360 // which is too small for a secure, random nonce. Therefore we 361 // use the sequence number as the nonce. 362 explicitIVIsSeq = true 363 } 364 } else if _, ok := c.out.cipher.(nullCipher); !ok && c.out.cipher != nil { 365 panic("Unknown cipher") 366 } 367 b.resize(recordHeaderLen + explicitIVLen + len(data)) 368 // TODO(nharper): DTLS 1.3 will likely need to set this to 369 // recordTypeApplicationData if c.out.cipher != nil. 370 b.data[0] = byte(typ) 371 vers := c.vers 372 if vers == 0 { 373 // Some TLS servers fail if the record version is greater than 374 // TLS 1.0 for the initial ClientHello. 375 vers = VersionTLS10 376 } 377 vers = versionToWire(vers, c.isDTLS) 378 b.data[1] = byte(vers >> 8) 379 b.data[2] = byte(vers) 380 // DTLS records include an explicit sequence number. 381 copy(b.data[3:11], c.out.outSeq[0:]) 382 b.data[11] = byte(len(data) >> 8) 383 b.data[12] = byte(len(data)) 384 if explicitIVLen > 0 { 385 explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen] 386 if explicitIVIsSeq { 387 copy(explicitIV, c.out.outSeq[:]) 388 } else { 389 if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil { 390 return 391 } 392 } 393 } 394 copy(b.data[recordHeaderLen+explicitIVLen:], data) 395 c.out.encrypt(b, explicitIVLen, typ) 396 return 397} 398 399func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) { 400 b, err := c.dtlsSealRecord(typ, data) 401 if err != nil { 402 return 403 } 404 405 _, err = c.conn.Write(b.data) 406 if err != nil { 407 return 408 } 409 n = len(data) 410 411 c.out.freeBlock(b) 412 return 413} 414 415func (c *Conn) dtlsDoReadHandshake() ([]byte, error) { 416 // Assemble a full handshake message. For test purposes, this 417 // implementation assumes fragments arrive in order. It may 418 // need to be cleverer if we ever test BoringSSL's retransmit 419 // behavior. 420 for len(c.handMsg) < 4+c.handMsgLen { 421 // Get a new handshake record if the previous has been 422 // exhausted. 423 if c.hand.Len() == 0 { 424 if err := c.in.err; err != nil { 425 return nil, err 426 } 427 if err := c.readRecord(recordTypeHandshake); err != nil { 428 return nil, err 429 } 430 } 431 432 // Read the next fragment. It must fit entirely within 433 // the record. 434 if c.hand.Len() < 12 { 435 return nil, errors.New("dtls: bad handshake record") 436 } 437 header := c.hand.Next(12) 438 fragN := int(header[1])<<16 | int(header[2])<<8 | int(header[3]) 439 fragSeq := uint16(header[4])<<8 | uint16(header[5]) 440 fragOff := int(header[6])<<16 | int(header[7])<<8 | int(header[8]) 441 fragLen := int(header[9])<<16 | int(header[10])<<8 | int(header[11]) 442 443 if c.hand.Len() < fragLen { 444 return nil, errors.New("dtls: fragment length too long") 445 } 446 fragment := c.hand.Next(fragLen) 447 448 // Check it's a fragment for the right message. 449 if fragSeq != c.recvHandshakeSeq { 450 return nil, errors.New("dtls: bad handshake sequence number") 451 } 452 453 // Check that the length is consistent. 454 if c.handMsg == nil { 455 c.handMsgLen = fragN 456 if c.handMsgLen > maxHandshake { 457 return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError)) 458 } 459 // Start with the TLS handshake header, 460 // without the DTLS bits. 461 c.handMsg = append([]byte{}, header[:4]...) 462 } else if fragN != c.handMsgLen { 463 return nil, errors.New("dtls: bad handshake length") 464 } 465 466 // Add the fragment to the pending message. 467 if 4+fragOff != len(c.handMsg) { 468 return nil, errors.New("dtls: bad fragment offset") 469 } 470 if fragOff+fragLen > c.handMsgLen { 471 return nil, errors.New("dtls: bad fragment length") 472 } 473 c.handMsg = append(c.handMsg, fragment...) 474 } 475 c.recvHandshakeSeq++ 476 ret := c.handMsg 477 c.handMsg, c.handMsgLen = nil, 0 478 return ret, nil 479} 480 481// DTLSServer returns a new DTLS server side connection 482// using conn as the underlying transport. 483// The configuration config must be non-nil and must have 484// at least one certificate. 485func DTLSServer(conn net.Conn, config *Config) *Conn { 486 c := &Conn{config: config, isDTLS: true, conn: conn} 487 c.init() 488 return c 489} 490 491// DTLSClient returns a new DTLS client side connection 492// using conn as the underlying transport. 493// The config cannot be nil: users must set either ServerHostname or 494// InsecureSkipVerify in the config. 495func DTLSClient(conn net.Conn, config *Config) *Conn { 496 c := &Conn{config: config, isClient: true, isDTLS: true, conn: conn} 497 c.init() 498 return c 499} 500