1// Copyright 2011 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 5package ssh 6 7import ( 8 "crypto/aes" 9 "crypto/cipher" 10 "crypto/rc4" 11 "crypto/subtle" 12 "encoding/binary" 13 "errors" 14 "fmt" 15 "hash" 16 "io" 17 "io/ioutil" 18) 19 20const ( 21 packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. 22 23 // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations 24 // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC 25 // indicates implementations SHOULD be able to handle larger packet sizes, but then 26 // waffles on about reasonable limits. 27 // 28 // OpenSSH caps their maxPacket at 256kB so we choose to do 29 // the same. maxPacket is also used to ensure that uint32 30 // length fields do not overflow, so it should remain well 31 // below 4G. 32 maxPacket = 256 * 1024 33) 34 35// noneCipher implements cipher.Stream and provides no encryption. It is used 36// by the transport before the first key-exchange. 37type noneCipher struct{} 38 39func (c noneCipher) XORKeyStream(dst, src []byte) { 40 copy(dst, src) 41} 42 43func newAESCTR(key, iv []byte) (cipher.Stream, error) { 44 c, err := aes.NewCipher(key) 45 if err != nil { 46 return nil, err 47 } 48 return cipher.NewCTR(c, iv), nil 49} 50 51func newRC4(key, iv []byte) (cipher.Stream, error) { 52 return rc4.NewCipher(key) 53} 54 55type streamCipherMode struct { 56 keySize int 57 ivSize int 58 skip int 59 createFunc func(key, iv []byte) (cipher.Stream, error) 60} 61 62func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) { 63 if len(key) < c.keySize { 64 panic("ssh: key length too small for cipher") 65 } 66 if len(iv) < c.ivSize { 67 panic("ssh: iv too small for cipher") 68 } 69 70 stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize]) 71 if err != nil { 72 return nil, err 73 } 74 75 var streamDump []byte 76 if c.skip > 0 { 77 streamDump = make([]byte, 512) 78 } 79 80 for remainingToDump := c.skip; remainingToDump > 0; { 81 dumpThisTime := remainingToDump 82 if dumpThisTime > len(streamDump) { 83 dumpThisTime = len(streamDump) 84 } 85 stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) 86 remainingToDump -= dumpThisTime 87 } 88 89 return stream, nil 90} 91 92// cipherModes documents properties of supported ciphers. Ciphers not included 93// are not supported and will not be negotiated, even if explicitly requested in 94// ClientConfig.Crypto.Ciphers. 95var cipherModes = map[string]*streamCipherMode{ 96 // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms 97 // are defined in the order specified in the RFC. 98 "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, 99 "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, 100 "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, 101 102 // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. 103 // They are defined in the order specified in the RFC. 104 "arcfour128": {16, 0, 1536, newRC4}, 105 "arcfour256": {32, 0, 1536, newRC4}, 106 107 // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. 108 // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and 109 // RC4) has problems with weak keys, and should be used with caution." 110 // RFC4345 introduces improved versions of Arcfour. 111 "arcfour": {16, 0, 0, newRC4}, 112 113 // AES-GCM is not a stream cipher, so it is constructed with a 114 // special case. If we add any more non-stream ciphers, we 115 // should invest a cleaner way to do this. 116 gcmCipherID: {16, 12, 0, nil}, 117 118 // CBC mode is insecure and so is not included in the default config. 119 // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely 120 // needed, it's possible to specify a custom Config to enable it. 121 // You should expect that an active attacker can recover plaintext if 122 // you do. 123 aes128cbcID: {16, aes.BlockSize, 0, nil}, 124} 125 126// prefixLen is the length of the packet prefix that contains the packet length 127// and number of padding bytes. 128const prefixLen = 5 129 130// streamPacketCipher is a packetCipher using a stream cipher. 131type streamPacketCipher struct { 132 mac hash.Hash 133 cipher cipher.Stream 134 135 // The following members are to avoid per-packet allocations. 136 prefix [prefixLen]byte 137 seqNumBytes [4]byte 138 padding [2 * packetSizeMultiple]byte 139 packetData []byte 140 macResult []byte 141} 142 143// readPacket reads and decrypt a single packet from the reader argument. 144func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { 145 if _, err := io.ReadFull(r, s.prefix[:]); err != nil { 146 return nil, err 147 } 148 149 s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) 150 length := binary.BigEndian.Uint32(s.prefix[0:4]) 151 paddingLength := uint32(s.prefix[4]) 152 153 var macSize uint32 154 if s.mac != nil { 155 s.mac.Reset() 156 binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) 157 s.mac.Write(s.seqNumBytes[:]) 158 s.mac.Write(s.prefix[:]) 159 macSize = uint32(s.mac.Size()) 160 } 161 162 if length <= paddingLength+1 { 163 return nil, errors.New("ssh: invalid packet length, packet too small") 164 } 165 166 if length > maxPacket { 167 return nil, errors.New("ssh: invalid packet length, packet too large") 168 } 169 170 // the maxPacket check above ensures that length-1+macSize 171 // does not overflow. 172 if uint32(cap(s.packetData)) < length-1+macSize { 173 s.packetData = make([]byte, length-1+macSize) 174 } else { 175 s.packetData = s.packetData[:length-1+macSize] 176 } 177 178 if _, err := io.ReadFull(r, s.packetData); err != nil { 179 return nil, err 180 } 181 mac := s.packetData[length-1:] 182 data := s.packetData[:length-1] 183 s.cipher.XORKeyStream(data, data) 184 185 if s.mac != nil { 186 s.mac.Write(data) 187 s.macResult = s.mac.Sum(s.macResult[:0]) 188 if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { 189 return nil, errors.New("ssh: MAC failure") 190 } 191 } 192 193 return s.packetData[:length-paddingLength-1], nil 194} 195 196// writePacket encrypts and sends a packet of data to the writer argument 197func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { 198 if len(packet) > maxPacket { 199 return errors.New("ssh: packet too large") 200 } 201 202 paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple 203 if paddingLength < 4 { 204 paddingLength += packetSizeMultiple 205 } 206 207 length := len(packet) + 1 + paddingLength 208 binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) 209 s.prefix[4] = byte(paddingLength) 210 padding := s.padding[:paddingLength] 211 if _, err := io.ReadFull(rand, padding); err != nil { 212 return err 213 } 214 215 if s.mac != nil { 216 s.mac.Reset() 217 binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) 218 s.mac.Write(s.seqNumBytes[:]) 219 s.mac.Write(s.prefix[:]) 220 s.mac.Write(packet) 221 s.mac.Write(padding) 222 } 223 224 s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) 225 s.cipher.XORKeyStream(packet, packet) 226 s.cipher.XORKeyStream(padding, padding) 227 228 if _, err := w.Write(s.prefix[:]); err != nil { 229 return err 230 } 231 if _, err := w.Write(packet); err != nil { 232 return err 233 } 234 if _, err := w.Write(padding); err != nil { 235 return err 236 } 237 238 if s.mac != nil { 239 s.macResult = s.mac.Sum(s.macResult[:0]) 240 if _, err := w.Write(s.macResult); err != nil { 241 return err 242 } 243 } 244 245 return nil 246} 247 248type gcmCipher struct { 249 aead cipher.AEAD 250 prefix [4]byte 251 iv []byte 252 buf []byte 253} 254 255func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) { 256 c, err := aes.NewCipher(key) 257 if err != nil { 258 return nil, err 259 } 260 261 aead, err := cipher.NewGCM(c) 262 if err != nil { 263 return nil, err 264 } 265 266 return &gcmCipher{ 267 aead: aead, 268 iv: iv, 269 }, nil 270} 271 272const gcmTagSize = 16 273 274func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { 275 // Pad out to multiple of 16 bytes. This is different from the 276 // stream cipher because that encrypts the length too. 277 padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) 278 if padding < 4 { 279 padding += packetSizeMultiple 280 } 281 282 length := uint32(len(packet) + int(padding) + 1) 283 binary.BigEndian.PutUint32(c.prefix[:], length) 284 if _, err := w.Write(c.prefix[:]); err != nil { 285 return err 286 } 287 288 if cap(c.buf) < int(length) { 289 c.buf = make([]byte, length) 290 } else { 291 c.buf = c.buf[:length] 292 } 293 294 c.buf[0] = padding 295 copy(c.buf[1:], packet) 296 if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { 297 return err 298 } 299 c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) 300 if _, err := w.Write(c.buf); err != nil { 301 return err 302 } 303 c.incIV() 304 305 return nil 306} 307 308func (c *gcmCipher) incIV() { 309 for i := 4 + 7; i >= 4; i-- { 310 c.iv[i]++ 311 if c.iv[i] != 0 { 312 break 313 } 314 } 315} 316 317func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { 318 if _, err := io.ReadFull(r, c.prefix[:]); err != nil { 319 return nil, err 320 } 321 length := binary.BigEndian.Uint32(c.prefix[:]) 322 if length > maxPacket { 323 return nil, errors.New("ssh: max packet length exceeded.") 324 } 325 326 if cap(c.buf) < int(length+gcmTagSize) { 327 c.buf = make([]byte, length+gcmTagSize) 328 } else { 329 c.buf = c.buf[:length+gcmTagSize] 330 } 331 332 if _, err := io.ReadFull(r, c.buf); err != nil { 333 return nil, err 334 } 335 336 plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) 337 if err != nil { 338 return nil, err 339 } 340 c.incIV() 341 342 padding := plain[0] 343 if padding < 4 || padding >= 20 { 344 return nil, fmt.Errorf("ssh: illegal padding %d", padding) 345 } 346 347 if int(padding+1) >= len(plain) { 348 return nil, fmt.Errorf("ssh: padding %d too large", padding) 349 } 350 plain = plain[1 : length-uint32(padding)] 351 return plain, nil 352} 353 354// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 355type cbcCipher struct { 356 mac hash.Hash 357 macSize uint32 358 decrypter cipher.BlockMode 359 encrypter cipher.BlockMode 360 361 // The following members are to avoid per-packet allocations. 362 seqNumBytes [4]byte 363 packetData []byte 364 macResult []byte 365 366 // Amount of data we should still read to hide which 367 // verification error triggered. 368 oracleCamouflage uint32 369} 370 371func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { 372 c, err := aes.NewCipher(key) 373 if err != nil { 374 return nil, err 375 } 376 377 cbc := &cbcCipher{ 378 mac: macModes[algs.MAC].new(macKey), 379 decrypter: cipher.NewCBCDecrypter(c, iv), 380 encrypter: cipher.NewCBCEncrypter(c, iv), 381 packetData: make([]byte, 1024), 382 } 383 if cbc.mac != nil { 384 cbc.macSize = uint32(cbc.mac.Size()) 385 } 386 387 return cbc, nil 388} 389 390func maxUInt32(a, b int) uint32 { 391 if a > b { 392 return uint32(a) 393 } 394 return uint32(b) 395} 396 397const ( 398 cbcMinPacketSizeMultiple = 8 399 cbcMinPacketSize = 16 400 cbcMinPaddingSize = 4 401) 402 403// cbcError represents a verification error that may leak information. 404type cbcError string 405 406func (e cbcError) Error() string { return string(e) } 407 408func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { 409 p, err := c.readPacketLeaky(seqNum, r) 410 if err != nil { 411 if _, ok := err.(cbcError); ok { 412 // Verification error: read a fixed amount of 413 // data, to make distinguishing between 414 // failing MAC and failing length check more 415 // difficult. 416 io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage)) 417 } 418 } 419 return p, err 420} 421 422func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { 423 blockSize := c.decrypter.BlockSize() 424 425 // Read the header, which will include some of the subsequent data in the 426 // case of block ciphers - this is copied back to the payload later. 427 // How many bytes of payload/padding will be read with this first read. 428 firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) 429 firstBlock := c.packetData[:firstBlockLength] 430 if _, err := io.ReadFull(r, firstBlock); err != nil { 431 return nil, err 432 } 433 434 c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength 435 436 c.decrypter.CryptBlocks(firstBlock, firstBlock) 437 length := binary.BigEndian.Uint32(firstBlock[:4]) 438 if length > maxPacket { 439 return nil, cbcError("ssh: packet too large") 440 } 441 if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { 442 // The minimum size of a packet is 16 (or the cipher block size, whichever 443 // is larger) bytes. 444 return nil, cbcError("ssh: packet too small") 445 } 446 // The length of the packet (including the length field but not the MAC) must 447 // be a multiple of the block size or 8, whichever is larger. 448 if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { 449 return nil, cbcError("ssh: invalid packet length multiple") 450 } 451 452 paddingLength := uint32(firstBlock[4]) 453 if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { 454 return nil, cbcError("ssh: invalid packet length") 455 } 456 457 // Positions within the c.packetData buffer: 458 macStart := 4 + length 459 paddingStart := macStart - paddingLength 460 461 // Entire packet size, starting before length, ending at end of mac. 462 entirePacketSize := macStart + c.macSize 463 464 // Ensure c.packetData is large enough for the entire packet data. 465 if uint32(cap(c.packetData)) < entirePacketSize { 466 // Still need to upsize and copy, but this should be rare at runtime, only 467 // on upsizing the packetData buffer. 468 c.packetData = make([]byte, entirePacketSize) 469 copy(c.packetData, firstBlock) 470 } else { 471 c.packetData = c.packetData[:entirePacketSize] 472 } 473 474 if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil { 475 return nil, err 476 } else { 477 c.oracleCamouflage -= uint32(n) 478 } 479 480 remainingCrypted := c.packetData[firstBlockLength:macStart] 481 c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) 482 483 mac := c.packetData[macStart:] 484 if c.mac != nil { 485 c.mac.Reset() 486 binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) 487 c.mac.Write(c.seqNumBytes[:]) 488 c.mac.Write(c.packetData[:macStart]) 489 c.macResult = c.mac.Sum(c.macResult[:0]) 490 if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { 491 return nil, cbcError("ssh: MAC failure") 492 } 493 } 494 495 return c.packetData[prefixLen:paddingStart], nil 496} 497 498func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { 499 effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) 500 501 // Length of encrypted portion of the packet (header, payload, padding). 502 // Enforce minimum padding and packet size. 503 encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) 504 // Enforce block size. 505 encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize 506 507 length := encLength - 4 508 paddingLength := int(length) - (1 + len(packet)) 509 510 // Overall buffer contains: header, payload, padding, mac. 511 // Space for the MAC is reserved in the capacity but not the slice length. 512 bufferSize := encLength + c.macSize 513 if uint32(cap(c.packetData)) < bufferSize { 514 c.packetData = make([]byte, encLength, bufferSize) 515 } else { 516 c.packetData = c.packetData[:encLength] 517 } 518 519 p := c.packetData 520 521 // Packet header. 522 binary.BigEndian.PutUint32(p, length) 523 p = p[4:] 524 p[0] = byte(paddingLength) 525 526 // Payload. 527 p = p[1:] 528 copy(p, packet) 529 530 // Padding. 531 p = p[len(packet):] 532 if _, err := io.ReadFull(rand, p); err != nil { 533 return err 534 } 535 536 if c.mac != nil { 537 c.mac.Reset() 538 binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) 539 c.mac.Write(c.seqNumBytes[:]) 540 c.mac.Write(c.packetData) 541 // The MAC is now appended into the capacity reserved for it earlier. 542 c.packetData = c.mac.Sum(c.packetData) 543 } 544 545 c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) 546 547 if _, err := w.Write(c.packetData); err != nil { 548 return err 549 } 550 551 return nil 552} 553