1// Copyright 2012 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
7// Message authentication support
8
9import (
10 "crypto/fips140"
11 "crypto/hmac"
12 "crypto/sha1"
13 "crypto/sha256"
14 "crypto/sha512"
15 "hash"
16 "slices"
17)
18
19type macMode struct {
20 keySize int
21 etm bool
22 new func(key []byte) hash.Hash
23}
24
25// truncatingMAC wraps around a hash.Hash and truncates the output digest to
26// a given size.
27type truncatingMAC struct {
28 length int
29 hmac hash.Hash
30}
31
32func (t truncatingMAC) Write(data []byte) (int, error) {
33 return t.hmac.Write(data)
34}
35
36func (t truncatingMAC) Sum(in []byte) []byte {
37 out := t.hmac.Sum(in)
38 return out[:len(in)+t.length]
39}
40
41func (t truncatingMAC) Reset() {
42 t.hmac.Reset()
43}
44
45func (t truncatingMAC) Size() int {
46 return t.length
47}
48
49func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
50
51// macModes defines the supported MACs. MACs not included are not supported
52// and will not be negotiated, even if explicitly configured. When FIPS mode is
53// enabled, only FIPS-approved algorithms are included.
54var macModes = map[string]*macMode{}
55
56func init() {
57 macModes[HMACSHA512ETM] = &macMode{64, true, func(key []byte) hash.Hash {
58 return hmac.New(sha512.New, key)
59 }}
60 macModes[HMACSHA256ETM] = &macMode{32, true, func(key []byte) hash.Hash {
61 return hmac.New(sha256.New, key)
62 }}
63 macModes[HMACSHA512] = &macMode{64, false, func(key []byte) hash.Hash {
64 return hmac.New(sha512.New, key)
65 }}
66 macModes[HMACSHA256] = &macMode{32, false, func(key []byte) hash.Hash {
67 return hmac.New(sha256.New, key)
68 }}
69
70 if fips140.Enabled() {
71 defaultMACs = slices.DeleteFunc(defaultMACs, func(algo string) bool {
72 _, ok := macModes[algo]
73 return !ok
74 })
75 return
76 }
77
78 macModes[HMACSHA1] = &macMode{20, false, func(key []byte) hash.Hash {
79 return hmac.New(sha1.New, key)
80 }}
81 macModes[InsecureHMACSHA196] = &macMode{20, false, func(key []byte) hash.Hash {
82 return truncatingMAC{12, hmac.New(sha1.New, key)}
83 }}
84}