mac.go raw
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
5 package ssh
6
7 // Message authentication support
8
9 import (
10 "crypto/fips140"
11 "crypto/hmac"
12 "crypto/sha1"
13 "crypto/sha256"
14 "crypto/sha512"
15 "hash"
16 "slices"
17 )
18
19 type 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.
27 type truncatingMAC struct {
28 length int
29 hmac hash.Hash
30 }
31
32 func (t truncatingMAC) Write(data []byte) (int, error) {
33 return t.hmac.Write(data)
34 }
35
36 func (t truncatingMAC) Sum(in []byte) []byte {
37 out := t.hmac.Sum(in)
38 return out[:len(in)+t.length]
39 }
40
41 func (t truncatingMAC) Reset() {
42 t.hmac.Reset()
43 }
44
45 func (t truncatingMAC) Size() int {
46 return t.length
47 }
48
49 func (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.
54 var macModes = map[string]*macMode{}
55
56 func 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 }
85