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