1
2
3
4
5
6
7
8 package hmac
9
10 import (
11 "crypto/internal/fips140"
12 "crypto/internal/fips140/sha256"
13 "crypto/internal/fips140/sha3"
14 "crypto/internal/fips140/sha512"
15 "errors"
16 "hash"
17 )
18
19
20
21
22
23
24
25
26
27 type marshalable interface {
28 MarshalBinary() ([]byte, error)
29 UnmarshalBinary([]byte) error
30 }
31
32 type HMAC struct {
33
34 opad, ipad []byte
35 outer, inner hash.Hash
36
37
38
39
40 marshaled bool
41
42
43 forHKDF bool
44 keyLen int
45 }
46
47 func (h *HMAC) Sum(in []byte) []byte {
48
49
50
51 if h.keyLen < 112/8 && !h.forHKDF {
52 fips140.RecordNonApproved()
53 }
54 switch h.inner.(type) {
55 case *sha256.Digest, *sha512.Digest, *sha3.Digest:
56 default:
57 fips140.RecordNonApproved()
58 }
59
60 origLen := len(in)
61 in = h.inner.Sum(in)
62
63 if h.marshaled {
64 if err := h.outer.(marshalable).UnmarshalBinary(h.opad); err != nil {
65 panic(err)
66 }
67 } else {
68 h.outer.Reset()
69 h.outer.Write(h.opad)
70 }
71 h.outer.Write(in[origLen:])
72 return h.outer.Sum(in[:origLen])
73 }
74
75 func (h *HMAC) Write(p []byte) (n int, err error) {
76 return h.inner.Write(p)
77 }
78
79 func (h *HMAC) Size() int { return h.outer.Size() }
80 func (h *HMAC) BlockSize() int { return h.inner.BlockSize() }
81
82 func (h *HMAC) Reset() {
83 if h.marshaled {
84 if err := h.inner.(marshalable).UnmarshalBinary(h.ipad); err != nil {
85 panic(err)
86 }
87 return
88 }
89
90 h.inner.Reset()
91 h.inner.Write(h.ipad)
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 marshalableInner, innerOK := h.inner.(marshalable)
107 if !innerOK {
108 return
109 }
110 marshalableOuter, outerOK := h.outer.(marshalable)
111 if !outerOK {
112 return
113 }
114
115 imarshal, err := marshalableInner.MarshalBinary()
116 if err != nil {
117 return
118 }
119
120 h.outer.Reset()
121 h.outer.Write(h.opad)
122 omarshal, err := marshalableOuter.MarshalBinary()
123 if err != nil {
124 return
125 }
126
127
128 h.ipad = imarshal
129 h.opad = omarshal
130 h.marshaled = true
131 }
132
133 type errCloneUnsupported struct{}
134
135 func (e errCloneUnsupported) Error() string {
136 return "crypto/hmac: hash does not support hash.Cloner"
137 }
138
139 func (e errCloneUnsupported) Unwrap() error {
140 return errors.ErrUnsupported
141 }
142
143
144
145 func (h *HMAC) Clone() (hash.Cloner, error) {
146 r := *h
147 ic, ok := h.inner.(hash.Cloner)
148 if !ok {
149 return nil, errCloneUnsupported{}
150 }
151 oc, ok := h.outer.(hash.Cloner)
152 if !ok {
153 return nil, errCloneUnsupported{}
154 }
155 var err error
156 r.inner, err = ic.Clone()
157 if err != nil {
158 return nil, errCloneUnsupported{}
159 }
160 r.outer, err = oc.Clone()
161 if err != nil {
162 return nil, errCloneUnsupported{}
163 }
164 return &r, nil
165 }
166
167
168 func New[H hash.Hash](h func() H, key []byte) *HMAC {
169 hm := &HMAC{keyLen: len(key)}
170 hm.outer = h()
171 hm.inner = h()
172 unique := true
173 func() {
174 defer func() {
175
176 _ = recover()
177 }()
178 if hm.outer == hm.inner {
179 unique = false
180 }
181 }()
182 if !unique {
183 panic("crypto/hmac: hash generation function does not produce unique values")
184 }
185 blocksize := hm.inner.BlockSize()
186 hm.ipad = make([]byte, blocksize)
187 hm.opad = make([]byte, blocksize)
188 if len(key) > blocksize {
189
190 hm.outer.Write(key)
191 key = hm.outer.Sum(nil)
192 }
193 copy(hm.ipad, key)
194 copy(hm.opad, key)
195 for i := range hm.ipad {
196 hm.ipad[i] ^= 0x36
197 }
198 for i := range hm.opad {
199 hm.opad[i] ^= 0x5c
200 }
201 hm.inner.Write(hm.ipad)
202
203 return hm
204 }
205
206
207 func MarkAsUsedInKDF(h *HMAC) {
208 h.forHKDF = true
209 }
210
View as plain text