1 // Copyright 2009 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 hmac implements HMAC according to [FIPS 198-1].
6 //
7 // [FIPS 198-1]: https://doi.org/10.6028/NIST.FIPS.198-1
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 // key is zero padded to the block size of the hash function
20 // ipad = 0x36 byte repeated for key length
21 // opad = 0x5c byte repeated for key length
22 // hmac = H([key ^ opad] H([key ^ ipad] text))
23 24 // marshalable is the combination of encoding.BinaryMarshaler and
25 // encoding.BinaryUnmarshaler. Their method definitions are repeated here to
26 // avoid a dependency on the encoding package.
27 type marshalable interface {
28 MarshalBinary() ([]byte, error)
29 UnmarshalBinary([]byte) error
30 }
31 32 type HMAC struct {
33 // opad and ipad may share underlying storage with HMAC clones.
34 opad, ipad []byte
35 outer, inner hash.Hash
36 37 // If marshaled is true, then opad and ipad do not contain a padded
38 // copy of the key, but rather the marshaled state of outer/inner after
39 // opad/ipad has been fed into it.
40 marshaled bool
41 42 // forHKDF and keyLen are stored to inform the service indicator decision.
43 forHKDF bool
44 keyLen int
45 }
46 47 func (h *HMAC) Sum(in []byte) []byte {
48 // Per FIPS 140-3 IG C.M, key lengths below 112 bits are only allowed for
49 // legacy use (i.e. verification only) and we don't support that. However,
50 // HKDF uses the HMAC key for the salt, which is allowed to be shorter.
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 // If the underlying hash is marshalable, we can save some time by saving a
94 // copy of the hash state now, and restoring it on future calls to Reset and
95 // Sum instead of writing ipad/opad every time.
96 //
97 // We do this on Reset to avoid slowing down the common single-use case.
98 //
99 // This is allowed by FIPS 198-1, Section 6: "Conceptually, the intermediate
100 // results of the compression function on the B-byte blocks (K0 ⊕ ipad) and
101 // (K0 ⊕ opad) can be precomputed once, at the time of generation of the key
102 // K, or before its first use. These intermediate results can be stored and
103 // then used to initialize H each time that a message needs to be
104 // authenticated using the same key. [...] These stored intermediate values
105 // shall be treated and protected in the same manner as secret keys."
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 // Marshaling succeeded; save the marshaled state for later
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 // Clone implements [hash.Cloner] if the underlying hash does.
144 // Otherwise, it returns an error wrapping [errors.ErrUnsupported].
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 // New returns a new HMAC hash using the given [hash.Hash] type and key.
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 // The comparison might panic if the underlying types are not comparable.
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 = []byte{:blocksize}
187 hm.opad = []byte{:blocksize}
188 if len(key) > blocksize {
189 // If key is too big, hash it.
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 // MarkAsUsedInKDF records that this HMAC instance is used as part of a KDF.
207 func MarkAsUsedInKDF(h *HMAC) {
208 h.forHKDF = true
209 }
210