go.crypto/ssh: improve support for MAC algorithms
Also, add support for hmac-sha1. At the suggestion of AGL hmac-md5, and hmac-md5-96 support was not included. Fixes golang/go#3095. R=golang-dev, agl, huin CC=golang-dev https://golang.org/cl/5696065
This commit is contained in:
Родитель
9b05c27191
Коммит
6de97b525f
|
@ -62,8 +62,8 @@ func (c *ClientConn) handshake() error {
|
|||
ServerHostKeyAlgos: supportedHostKeyAlgos,
|
||||
CiphersClientServer: c.config.Crypto.ciphers(),
|
||||
CiphersServerClient: c.config.Crypto.ciphers(),
|
||||
MACsClientServer: supportedMACs,
|
||||
MACsServerClient: supportedMACs,
|
||||
MACsClientServer: c.config.Crypto.macs(),
|
||||
MACsServerClient: c.config.Crypto.macs(),
|
||||
CompressionClientServer: supportedCompressions,
|
||||
CompressionServerClient: supportedCompressions,
|
||||
}
|
||||
|
|
|
@ -255,3 +255,24 @@ func TestClientAuthRSAandDSA(t *testing.T) {
|
|||
}
|
||||
c.Close()
|
||||
}
|
||||
|
||||
func TestClientHMAC(t *testing.T) {
|
||||
kc := new(keychain)
|
||||
kc.keys = append(kc.keys, rsakey)
|
||||
for _, mac := range DefaultMACOrder {
|
||||
config := &ClientConfig{
|
||||
User: "testuser",
|
||||
Auth: []ClientAuth{
|
||||
ClientAuthKeyring(kc),
|
||||
},
|
||||
Crypto: CryptoConfig{
|
||||
MACs: []string{mac},
|
||||
},
|
||||
}
|
||||
c, err := Dial("tcp", newMockAuthServer(t), config)
|
||||
if err != nil {
|
||||
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ const (
|
|||
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
|
||||
hostAlgoRSA = "ssh-rsa"
|
||||
hostAlgoDSA = "ssh-dss"
|
||||
macSHA196 = "hmac-sha1-96"
|
||||
compressionNone = "none"
|
||||
serviceUserAuth = "ssh-userauth"
|
||||
serviceSSH = "ssh-connection"
|
||||
|
@ -25,7 +24,6 @@ const (
|
|||
|
||||
var supportedKexAlgos = []string{kexAlgoDH14SHA1}
|
||||
var supportedHostKeyAlgos = []string{hostAlgoRSA}
|
||||
var supportedMACs = []string{macSHA196}
|
||||
var supportedCompressions = []string{compressionNone}
|
||||
|
||||
// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
|
||||
|
@ -134,6 +132,9 @@ type CryptoConfig struct {
|
|||
// The allowed cipher algorithms. If unspecified then DefaultCipherOrder is
|
||||
// used.
|
||||
Ciphers []string
|
||||
|
||||
// The allowed MAC algorithms. If unspecified then DefaultMACOrder is used.
|
||||
MACs []string
|
||||
}
|
||||
|
||||
func (c *CryptoConfig) ciphers() []string {
|
||||
|
@ -143,6 +144,13 @@ func (c *CryptoConfig) ciphers() []string {
|
|||
return c.Ciphers
|
||||
}
|
||||
|
||||
func (c *CryptoConfig) macs() []string {
|
||||
if c.MACs == nil {
|
||||
return DefaultMACOrder
|
||||
}
|
||||
return c.MACs
|
||||
}
|
||||
|
||||
// serialize a signed slice according to RFC 4254 6.6.
|
||||
func serializeSignature(algoname string, sig []byte) []byte {
|
||||
switch algoname {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssh
|
||||
|
||||
// Message authentication support
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"hash"
|
||||
)
|
||||
|
||||
type macMode struct {
|
||||
keySize int
|
||||
new func(key []byte) hash.Hash
|
||||
}
|
||||
|
||||
// truncatingMAC wraps around a hash.Hash and truncates the output digest to
|
||||
// a given size.
|
||||
type truncatingMAC struct {
|
||||
length int
|
||||
hmac hash.Hash
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Write(data []byte) (int, error) {
|
||||
return t.hmac.Write(data)
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Sum(in []byte) []byte {
|
||||
out := t.hmac.Sum(in)
|
||||
return out[:len(in)+t.length]
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Reset() {
|
||||
t.hmac.Reset()
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Size() int {
|
||||
return t.length
|
||||
}
|
||||
|
||||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||
|
||||
// Specifies a default set of MAC algorithms and a preference order.
|
||||
// This is based on RFC 4253, section 6.4, with the removal of the
|
||||
// hmac-md5 variants as they have reached the end of their useful life.
|
||||
var DefaultMACOrder = []string{"hmac-sha1", "hmac-sha1-96"}
|
||||
|
||||
var macModes = map[string]*macMode{
|
||||
"hmac-sha1": {20, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha1.New, key)
|
||||
}},
|
||||
"hmac-sha1-96": {20, func(key []byte) hash.Hash {
|
||||
return truncatingMAC{12, hmac.New(sha1.New, key)}
|
||||
}},
|
||||
}
|
|
@ -228,8 +228,8 @@ func (s *ServerConn) Handshake() error {
|
|||
ServerHostKeyAlgos: supportedHostKeyAlgos,
|
||||
CiphersClientServer: s.config.Crypto.ciphers(),
|
||||
CiphersServerClient: s.config.Crypto.ciphers(),
|
||||
MACsClientServer: supportedMACs,
|
||||
MACsServerClient: supportedMACs,
|
||||
MACsClientServer: s.config.Crypto.macs(),
|
||||
MACsServerClient: s.config.Crypto.macs(),
|
||||
CompressionClientServer: supportedCompressions,
|
||||
CompressionServerClient: supportedCompressions,
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import (
|
|||
"bufio"
|
||||
"crypto"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"hash"
|
||||
|
@ -255,28 +253,22 @@ var (
|
|||
// (to setup server->client keys) or clientKeys (for client->server keys).
|
||||
func (c *common) setupKeys(d direction, K, H, sessionId []byte, hashFunc crypto.Hash) error {
|
||||
cipherMode := cipherModes[c.cipherAlgo]
|
||||
|
||||
macKeySize := 20
|
||||
macMode := macModes[c.macAlgo]
|
||||
|
||||
iv := make([]byte, cipherMode.ivSize)
|
||||
key := make([]byte, cipherMode.keySize)
|
||||
macKey := make([]byte, macKeySize)
|
||||
macKey := make([]byte, macMode.keySize)
|
||||
|
||||
h := hashFunc.New()
|
||||
generateKeyMaterial(iv, d.ivTag, K, H, sessionId, h)
|
||||
generateKeyMaterial(key, d.keyTag, K, H, sessionId, h)
|
||||
generateKeyMaterial(macKey, d.macKeyTag, K, H, sessionId, h)
|
||||
|
||||
c.mac = truncatingMAC{12, hmac.New(sha1.New, macKey)}
|
||||
c.mac = macMode.new(macKey)
|
||||
|
||||
cipher, err := cipherMode.createCipher(key, iv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.cipher = cipher
|
||||
|
||||
return nil
|
||||
var err error
|
||||
c.cipher, err = cipherMode.createCipher(key, iv)
|
||||
return err
|
||||
}
|
||||
|
||||
// generateKeyMaterial fills out with key material generated from tag, K, H
|
||||
|
@ -305,32 +297,6 @@ func generateKeyMaterial(out, tag []byte, K, H, sessionId []byte, h hash.Hash) {
|
|||
}
|
||||
}
|
||||
|
||||
// truncatingMAC wraps around a hash.Hash and truncates the output digest to
|
||||
// a given size.
|
||||
type truncatingMAC struct {
|
||||
length int
|
||||
hmac hash.Hash
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Write(data []byte) (int, error) {
|
||||
return t.hmac.Write(data)
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Sum(in []byte) []byte {
|
||||
out := t.hmac.Sum(in)
|
||||
return out[:len(in)+t.length]
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Reset() {
|
||||
t.hmac.Reset()
|
||||
}
|
||||
|
||||
func (t truncatingMAC) Size() int {
|
||||
return t.length
|
||||
}
|
||||
|
||||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||
|
||||
// maxVersionStringBytes is the maximum number of bytes that we'll accept as a
|
||||
// version string. In the event that the client is talking a different protocol
|
||||
// we need to set a limit otherwise we will keep using more and more memory
|
||||
|
|
Загрузка…
Ссылка в новой задаче