1// Copyright 2013 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
5package cipher
6
7import (
8	"crypto/internal/alias"
9	"crypto/subtle"
10	"errors"
11	"internal/byteorder"
12)
13
14// AEAD is a cipher mode providing authenticated encryption with associated
15// data. For a description of the methodology, see
16// https://en.wikipedia.org/wiki/Authenticated_encryption.
17type AEAD interface {
18	// NonceSize returns the size of the nonce that must be passed to Seal
19	// and Open.
20	NonceSize() int
21
22	// Overhead returns the maximum difference between the lengths of a
23	// plaintext and its ciphertext.
24	Overhead() int
25
26	// Seal encrypts and authenticates plaintext, authenticates the
27	// additional data and appends the result to dst, returning the updated
28	// slice. The nonce must be NonceSize() bytes long and unique for all
29	// time, for a given key.
30	//
31	// To reuse plaintext's storage for the encrypted output, use plaintext[:0]
32	// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
33	Seal(dst, nonce, plaintext, additionalData []byte) []byte
34
35	// Open decrypts and authenticates ciphertext, authenticates the
36	// additional data and, if successful, appends the resulting plaintext
37	// to dst, returning the updated slice. The nonce must be NonceSize()
38	// bytes long and both it and the additional data must match the
39	// value passed to Seal.
40	//
41	// To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
42	// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
43	//
44	// Even if the function fails, the contents of dst, up to its capacity,
45	// may be overwritten.
46	Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
47}
48
49// gcmAble is an interface implemented by ciphers that have a specific optimized
50// implementation of GCM, like crypto/aes. NewGCM will check for this interface
51// and return the specific AEAD if found.
52type gcmAble interface {
53	NewGCM(nonceSize, tagSize int) (AEAD, error)
54}
55
56// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
57// standard and make binary.BigEndian suitable for marshaling these values, the
58// bits are stored in big endian order. For example:
59//
60//	the coefficient of x⁰ can be obtained by v.low >> 63.
61//	the coefficient of x⁶³ can be obtained by v.low & 1.
62//	the coefficient of x⁶⁴ can be obtained by v.high >> 63.
63//	the coefficient of x¹²⁷ can be obtained by v.high & 1.
64type gcmFieldElement struct {
65	low, high uint64
66}
67
68// gcm represents a Galois Counter Mode with a specific key. See
69// https://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
70type gcm struct {
71	cipher    Block
72	nonceSize int
73	tagSize   int
74	// productTable contains the first sixteen powers of the key, H.
75	// However, they are in bit reversed order. See NewGCMWithNonceSize.
76	productTable [16]gcmFieldElement
77}
78
79// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode
80// with the standard nonce length.
81//
82// In general, the GHASH operation performed by this implementation of GCM is not constant-time.
83// An exception is when the underlying [Block] was created by aes.NewCipher
84// on systems with hardware support for AES. See the [crypto/aes] package documentation for details.
85func NewGCM(cipher Block) (AEAD, error) {
86	return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, gcmTagSize)
87}
88
89// NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois
90// Counter Mode, which accepts nonces of the given length. The length must not
91// be zero.
92//
93// Only use this function if you require compatibility with an existing
94// cryptosystem that uses non-standard nonce lengths. All other users should use
95// [NewGCM], which is faster and more resistant to misuse.
96func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
97	return newGCMWithNonceAndTagSize(cipher, size, gcmTagSize)
98}
99
100// NewGCMWithTagSize returns the given 128-bit, block cipher wrapped in Galois
101// Counter Mode, which generates tags with the given length.
102//
103// Tag sizes between 12 and 16 bytes are allowed.
104//
105// Only use this function if you require compatibility with an existing
106// cryptosystem that uses non-standard tag lengths. All other users should use
107// [NewGCM], which is more resistant to misuse.
108func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error) {
109	return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, tagSize)
110}
111
112func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, error) {
113	if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize {
114		return nil, errors.New("cipher: incorrect tag size given to GCM")
115	}
116
117	if nonceSize <= 0 {
118		return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised")
119	}
120
121	if cipher, ok := cipher.(gcmAble); ok {
122		return cipher.NewGCM(nonceSize, tagSize)
123	}
124
125	if cipher.BlockSize() != gcmBlockSize {
126		return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
127	}
128
129	var key [gcmBlockSize]byte
130	cipher.Encrypt(key[:], key[:])
131
132	g := &gcm{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize}
133
134	// We precompute 16 multiples of |key|. However, when we do lookups
135	// into this table we'll be using bits from a field element and
136	// therefore the bits will be in the reverse order. So normally one
137	// would expect, say, 4*key to be in index 4 of the table but due to
138	// this bit ordering it will actually be in index 0010 (base 2) = 2.
139	x := gcmFieldElement{
140		byteorder.BeUint64(key[:8]),
141		byteorder.BeUint64(key[8:]),
142	}
143	g.productTable[reverseBits(1)] = x
144
145	for i := 2; i < 16; i += 2 {
146		g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)])
147		g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x)
148	}
149
150	return g, nil
151}
152
153const (
154	gcmBlockSize         = 16
155	gcmTagSize           = 16
156	gcmMinimumTagSize    = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
157	gcmStandardNonceSize = 12
158)
159
160func (g *gcm) NonceSize() int {
161	return g.nonceSize
162}
163
164func (g *gcm) Overhead() int {
165	return g.tagSize
166}
167
168func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
169	if len(nonce) != g.nonceSize {
170		panic("crypto/cipher: incorrect nonce length given to GCM")
171	}
172	if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) {
173		panic("crypto/cipher: message too large for GCM")
174	}
175
176	ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
177	if alias.InexactOverlap(out, plaintext) {
178		panic("crypto/cipher: invalid buffer overlap")
179	}
180
181	var counter, tagMask [gcmBlockSize]byte
182	g.deriveCounter(&counter, nonce)
183
184	g.cipher.Encrypt(tagMask[:], counter[:])
185	gcmInc32(&counter)
186
187	g.counterCrypt(out, plaintext, &counter)
188
189	var tag [gcmTagSize]byte
190	g.auth(tag[:], out[:len(plaintext)], data, &tagMask)
191	copy(out[len(plaintext):], tag[:])
192
193	return ret
194}
195
196var errOpen = errors.New("cipher: message authentication failed")
197
198func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
199	if len(nonce) != g.nonceSize {
200		panic("crypto/cipher: incorrect nonce length given to GCM")
201	}
202	// Sanity check to prevent the authentication from always succeeding if an implementation
203	// leaves tagSize uninitialized, for example.
204	if g.tagSize < gcmMinimumTagSize {
205		panic("crypto/cipher: incorrect GCM tag size")
206	}
207
208	if len(ciphertext) < g.tagSize {
209		return nil, errOpen
210	}
211	if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+uint64(g.tagSize) {
212		return nil, errOpen
213	}
214
215	tag := ciphertext[len(ciphertext)-g.tagSize:]
216	ciphertext = ciphertext[:len(ciphertext)-g.tagSize]
217
218	var counter, tagMask [gcmBlockSize]byte
219	g.deriveCounter(&counter, nonce)
220
221	g.cipher.Encrypt(tagMask[:], counter[:])
222	gcmInc32(&counter)
223
224	var expectedTag [gcmTagSize]byte
225	g.auth(expectedTag[:], ciphertext, data, &tagMask)
226
227	ret, out := sliceForAppend(dst, len(ciphertext))
228	if alias.InexactOverlap(out, ciphertext) {
229		panic("crypto/cipher: invalid buffer overlap")
230	}
231
232	if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
233		// The AESNI code decrypts and authenticates concurrently, and
234		// so overwrites dst in the event of a tag mismatch. That
235		// behavior is mimicked here in order to be consistent across
236		// platforms.
237		clear(out)
238		return nil, errOpen
239	}
240
241	g.counterCrypt(out, ciphertext, &counter)
242
243	return ret, nil
244}
245
246// reverseBits reverses the order of the bits of 4-bit number in i.
247func reverseBits(i int) int {
248	i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
249	i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
250	return i
251}
252
253// gcmAdd adds two elements of GF(2¹²⁸) and returns the sum.
254func gcmAdd(x, y *gcmFieldElement) gcmFieldElement {
255	// Addition in a characteristic 2 field is just XOR.
256	return gcmFieldElement{x.low ^ y.low, x.high ^ y.high}
257}
258
259// gcmDouble returns the result of doubling an element of GF(2¹²⁸).
260func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) {
261	msbSet := x.high&1 == 1
262
263	// Because of the bit-ordering, doubling is actually a right shift.
264	double.high = x.high >> 1
265	double.high |= x.low << 63
266	double.low = x.low >> 1
267
268	// If the most-significant bit was set before shifting then it,
269	// conceptually, becomes a term of x^128. This is greater than the
270	// irreducible polynomial so the result has to be reduced. The
271	// irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to
272	// eliminate the term at x^128 which also means subtracting the other
273	// four terms. In characteristic 2 fields, subtraction == addition ==
274	// XOR.
275	if msbSet {
276		double.low ^= 0xe100000000000000
277	}
278
279	return
280}
281
282var gcmReductionTable = []uint16{
283	0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
284	0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
285}
286
287// mul sets y to y*H, where H is the GCM key, fixed during NewGCMWithNonceSize.
288func (g *gcm) mul(y *gcmFieldElement) {
289	var z gcmFieldElement
290
291	for i := 0; i < 2; i++ {
292		word := y.high
293		if i == 1 {
294			word = y.low
295		}
296
297		// Multiplication works by multiplying z by 16 and adding in
298		// one of the precomputed multiples of H.
299		for j := 0; j < 64; j += 4 {
300			msw := z.high & 0xf
301			z.high >>= 4
302			z.high |= z.low << 60
303			z.low >>= 4
304			z.low ^= uint64(gcmReductionTable[msw]) << 48
305
306			// the values in |table| are ordered for
307			// little-endian bit positions. See the comment
308			// in NewGCMWithNonceSize.
309			t := &g.productTable[word&0xf]
310
311			z.low ^= t.low
312			z.high ^= t.high
313			word >>= 4
314		}
315	}
316
317	*y = z
318}
319
320// updateBlocks extends y with more polynomial terms from blocks, based on
321// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks.
322func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) {
323	for len(blocks) > 0 {
324		y.low ^= byteorder.BeUint64(blocks)
325		y.high ^= byteorder.BeUint64(blocks[8:])
326		g.mul(y)
327		blocks = blocks[gcmBlockSize:]
328	}
329}
330
331// update extends y with more polynomial terms from data. If data is not a
332// multiple of gcmBlockSize bytes long then the remainder is zero padded.
333func (g *gcm) update(y *gcmFieldElement, data []byte) {
334	fullBlocks := (len(data) >> 4) << 4
335	g.updateBlocks(y, data[:fullBlocks])
336
337	if len(data) != fullBlocks {
338		var partialBlock [gcmBlockSize]byte
339		copy(partialBlock[:], data[fullBlocks:])
340		g.updateBlocks(y, partialBlock[:])
341	}
342}
343
344// gcmInc32 treats the final four bytes of counterBlock as a big-endian value
345// and increments it.
346func gcmInc32(counterBlock *[16]byte) {
347	ctr := counterBlock[len(counterBlock)-4:]
348	byteorder.BePutUint32(ctr, byteorder.BeUint32(ctr)+1)
349}
350
351// sliceForAppend takes a slice and a requested number of bytes. It returns a
352// slice with the contents of the given slice followed by that many bytes and a
353// second slice that aliases into it and contains only the extra bytes. If the
354// original slice has sufficient capacity then no allocation is performed.
355func sliceForAppend(in []byte, n int) (head, tail []byte) {
356	if total := len(in) + n; cap(in) >= total {
357		head = in[:total]
358	} else {
359		head = make([]byte, total)
360		copy(head, in)
361	}
362	tail = head[len(in):]
363	return
364}
365
366// counterCrypt crypts in to out using g.cipher in counter mode.
367func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
368	var mask [gcmBlockSize]byte
369
370	for len(in) >= gcmBlockSize {
371		g.cipher.Encrypt(mask[:], counter[:])
372		gcmInc32(counter)
373
374		subtle.XORBytes(out, in, mask[:])
375		out = out[gcmBlockSize:]
376		in = in[gcmBlockSize:]
377	}
378
379	if len(in) > 0 {
380		g.cipher.Encrypt(mask[:], counter[:])
381		gcmInc32(counter)
382		subtle.XORBytes(out, in, mask[:])
383	}
384}
385
386// deriveCounter computes the initial GCM counter state from the given nonce.
387// See NIST SP 800-38D, section 7.1. This assumes that counter is filled with
388// zeros on entry.
389func (g *gcm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) {
390	// GCM has two modes of operation with respect to the initial counter
391	// state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path"
392	// for nonces of other lengths. For a 96-bit nonce, the nonce, along
393	// with a four-byte big-endian counter starting at one, is used
394	// directly as the starting counter. For other nonce sizes, the counter
395	// is computed by passing it through the GHASH function.
396	if len(nonce) == gcmStandardNonceSize {
397		copy(counter[:], nonce)
398		counter[gcmBlockSize-1] = 1
399	} else {
400		var y gcmFieldElement
401		g.update(&y, nonce)
402		y.high ^= uint64(len(nonce)) * 8
403		g.mul(&y)
404		byteorder.BePutUint64(counter[:8], y.low)
405		byteorder.BePutUint64(counter[8:], y.high)
406	}
407}
408
409// auth calculates GHASH(ciphertext, additionalData), masks the result with
410// tagMask and writes the result to out.
411func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) {
412	var y gcmFieldElement
413	g.update(&y, additionalData)
414	g.update(&y, ciphertext)
415
416	y.low ^= uint64(len(additionalData)) * 8
417	y.high ^= uint64(len(ciphertext)) * 8
418
419	g.mul(&y)
420
421	byteorder.BePutUint64(out, y.low)
422	byteorder.BePutUint64(out[8:], y.high)
423
424	subtle.XORBytes(out, out, tagMask[:])
425}
426