1
2
3
4
5 package gcm
6
7 import (
8 "crypto/internal/fips140"
9 "crypto/internal/fips140/aes"
10 "crypto/internal/fips140/alias"
11 "crypto/internal/fips140/drbg"
12 "crypto/internal/fips140deps/byteorder"
13 "errors"
14 "math"
15 )
16
17
18
19
20
21
22
23
24
25 func SealWithRandomNonce(g *GCM, nonce, out, plaintext, additionalData []byte) {
26 if uint64(len(plaintext)) > uint64((1<<32)-2)*gcmBlockSize {
27 panic("crypto/cipher: message too large for GCM")
28 }
29 if len(nonce) != gcmStandardNonceSize {
30 panic("crypto/cipher: incorrect nonce length given to GCMWithRandomNonce")
31 }
32 if len(out) != len(plaintext)+gcmTagSize {
33 panic("crypto/cipher: incorrect output length given to GCMWithRandomNonce")
34 }
35 if alias.InexactOverlap(out, plaintext) {
36 panic("crypto/cipher: invalid buffer overlap of output and input")
37 }
38 if alias.AnyOverlap(out, additionalData) {
39 panic("crypto/cipher: invalid buffer overlap of output and additional data")
40 }
41 fips140.RecordApproved()
42 drbg.Read(nonce)
43 seal(out, g, nonce, plaintext, additionalData)
44 }
45
46
47
48
49
50
51
52
53
54 func NewGCMWithCounterNonce(cipher *aes.Block) (*GCMWithCounterNonce, error) {
55 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
56 if err != nil {
57 return nil, err
58 }
59 return &GCMWithCounterNonce{g: *g}, nil
60 }
61
62
63
64
65
66
67 func NewGCMForTLS12(cipher *aes.Block) (*GCMWithCounterNonce, error) {
68 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
69 if err != nil {
70 return nil, err
71 }
72
73 return &GCMWithCounterNonce{g: *g, startReady: true}, nil
74 }
75
76
77
78
79
80 func NewGCMForSSH(cipher *aes.Block) (*GCMWithCounterNonce, error) {
81 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
82 if err != nil {
83 return nil, err
84 }
85 return &GCMWithCounterNonce{g: *g}, nil
86 }
87
88 type GCMWithCounterNonce struct {
89 g GCM
90 prefixReady bool
91 prefix uint32
92 startReady bool
93 start uint64
94 next uint64
95 }
96
97 func (g *GCMWithCounterNonce) NonceSize() int { return gcmStandardNonceSize }
98
99 func (g *GCMWithCounterNonce) Overhead() int { return gcmTagSize }
100
101
102
103
104
105 func (g *GCMWithCounterNonce) Seal(dst, nonce, plaintext, data []byte) []byte {
106 if len(nonce) != gcmStandardNonceSize {
107 panic("crypto/cipher: incorrect nonce length given to GCM")
108 }
109
110 if fips140.Enabled {
111 if !g.prefixReady {
112
113 g.prefixReady = true
114 g.prefix = byteorder.BEUint32(nonce[:4])
115 }
116 if g.prefix != byteorder.BEUint32(nonce[:4]) {
117 panic("crypto/cipher: GCM nonce prefix changed")
118 }
119
120 counter := byteorder.BEUint64(nonce[len(nonce)-8:])
121 if !g.startReady {
122
123 g.startReady = true
124 g.start = counter
125 }
126 counter -= g.start
127
128
129 if counter == math.MaxUint64 {
130 panic("crypto/cipher: counter exhausted")
131 }
132 if counter < g.next {
133 panic("crypto/cipher: counter decreased or remained the same")
134 }
135 g.next = counter + 1
136 }
137
138 fips140.RecordApproved()
139 return g.g.sealAfterIndicator(dst, nonce, plaintext, data)
140 }
141
142 func (g *GCMWithCounterNonce) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
143 fips140.RecordApproved()
144 return g.g.Open(dst, nonce, ciphertext, data)
145 }
146
147
148
149
150
151
152
153
154
155
156
157 func NewGCMWithXORCounterNonce(cipher *aes.Block) (*GCMWithXORCounterNonce, error) {
158 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
159 if err != nil {
160 return nil, err
161 }
162 return &GCMWithXORCounterNonce{g: *g}, nil
163 }
164
165
166
167
168
169 func NewGCMForTLS13(cipher *aes.Block) (*GCMWithXORCounterNonce, error) {
170 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
171 if err != nil {
172 return nil, err
173 }
174 return &GCMWithXORCounterNonce{g: *g}, nil
175 }
176
177
178
179
180
181 func NewGCMForHPKE(cipher *aes.Block) (*GCMWithXORCounterNonce, error) {
182 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
183 if err != nil {
184 return nil, err
185 }
186 return &GCMWithXORCounterNonce{g: *g}, nil
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200 func NewGCMForQUIC(cipher *aes.Block, iv []byte) (*GCMWithXORCounterNonce, error) {
201 g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize)
202 if err != nil {
203 return nil, err
204 }
205 gcm := &GCMWithXORCounterNonce{g: *g}
206 if err := gcm.SetNoncePrefixAndMask(iv); err != nil {
207 return nil, err
208 }
209 return gcm, nil
210 }
211
212 type GCMWithXORCounterNonce struct {
213 g GCM
214 ready bool
215 prefix uint32
216 mask uint64
217 next uint64
218 }
219
220
221
222
223
224
225
226
227
228
229 func (g *GCMWithXORCounterNonce) SetNoncePrefixAndMask(nonce []byte) error {
230 if len(nonce) != gcmStandardNonceSize {
231 return errors.New("crypto/cipher: incorrect nonce length given to SetNoncePrefixAndMask")
232 }
233 if g.ready {
234 return errors.New("crypto/cipher: SetNoncePrefixAndMask called twice or after first Seal")
235 }
236 g.prefix = byteorder.BEUint32(nonce[:4])
237 g.mask = byteorder.BEUint64(nonce[4:])
238 g.ready = true
239 return nil
240 }
241
242 func (g *GCMWithXORCounterNonce) NonceSize() int { return gcmStandardNonceSize }
243
244 func (g *GCMWithXORCounterNonce) Overhead() int { return gcmTagSize }
245
246
247
248
249
250 func (g *GCMWithXORCounterNonce) Seal(dst, nonce, plaintext, data []byte) []byte {
251 if len(nonce) != gcmStandardNonceSize {
252 panic("crypto/cipher: incorrect nonce length given to GCM")
253 }
254
255 if fips140.Enabled {
256 counter := byteorder.BEUint64(nonce[len(nonce)-8:])
257 if !g.ready {
258
259
260
261 g.ready = true
262 g.mask = counter
263 g.prefix = byteorder.BEUint32(nonce[:4])
264 }
265 if g.prefix != byteorder.BEUint32(nonce[:4]) {
266 panic("crypto/cipher: GCM nonce prefix changed")
267 }
268 counter ^= g.mask
269
270
271 if counter == math.MaxUint64 {
272 panic("crypto/cipher: counter exhausted")
273 }
274 if counter < g.next {
275 panic("crypto/cipher: counter decreased or remained the same")
276 }
277 g.next = counter + 1
278 }
279
280 fips140.RecordApproved()
281 return g.g.sealAfterIndicator(dst, nonce, plaintext, data)
282 }
283
284 func (g *GCMWithXORCounterNonce) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
285 fips140.RecordApproved()
286 return g.g.Open(dst, nonce, ciphertext, data)
287 }
288
View as plain text