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