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 5 package gcm
6 7 import (
8 "crypto/internal/fips140"
9 "crypto/internal/fips140/aes"
10 "crypto/internal/fips140/alias"
11 "errors"
12 )
13 14 // GCM represents a Galois Counter Mode with a specific key.
15 type GCM struct {
16 cipher aes.Block
17 nonceSize int
18 tagSize int
19 gcmPlatformData
20 }
21 22 func New(cipher *aes.Block, nonceSize, tagSize int) (*GCM, error) {
23 // This function is outlined to let the allocation happen on the parent stack.
24 return newGCM(&GCM{}, cipher, nonceSize, tagSize)
25 }
26 27 // newGCM is marked go:noinline to avoid it inlining into New, and making New
28 // too complex to inline itself.
29 //
30 //go:noinline
31 func newGCM(g *GCM, cipher *aes.Block, nonceSize, tagSize int) (*GCM, error) {
32 if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize {
33 return nil, errors.New("cipher: incorrect tag size given to GCM")
34 }
35 if nonceSize <= 0 {
36 return nil, errors.New("cipher: the nonce can't have zero length")
37 }
38 if cipher.BlockSize() != gcmBlockSize {
39 return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
40 }
41 g.cipher = *cipher
42 g.nonceSize = nonceSize
43 g.tagSize = tagSize
44 initGCM(g)
45 return g, nil
46 }
47 48 const (
49 gcmBlockSize = 16
50 gcmTagSize = 16
51 gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
52 gcmStandardNonceSize = 12
53 )
54 55 func (g *GCM) NonceSize() int {
56 return g.nonceSize
57 }
58 59 func (g *GCM) Overhead() int {
60 return g.tagSize
61 }
62 63 func (g *GCM) Seal(dst, nonce, plaintext, data []byte) []byte {
64 fips140.RecordNonApproved()
65 return g.sealAfterIndicator(dst, nonce, plaintext, data)
66 }
67 68 func (g *GCM) sealAfterIndicator(dst, nonce, plaintext, data []byte) []byte {
69 if len(nonce) != g.nonceSize {
70 panic("crypto/cipher: incorrect nonce length given to GCM")
71 }
72 if g.nonceSize == 0 {
73 panic("crypto/cipher: incorrect GCM nonce size")
74 }
75 if uint64(len(plaintext)) > uint64((1<<32)-2)*gcmBlockSize {
76 panic("crypto/cipher: message too large for GCM")
77 }
78 79 ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
80 if alias.InexactOverlap(out, plaintext) {
81 panic("crypto/cipher: invalid buffer overlap of output and input")
82 }
83 if alias.AnyOverlap(out, data) {
84 panic("crypto/cipher: invalid buffer overlap of output and additional data")
85 }
86 87 seal(out, g, nonce, plaintext, data)
88 return ret
89 }
90 91 var errOpen = errors.New("cipher: message authentication failed")
92 93 func (g *GCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
94 if len(nonce) != g.nonceSize {
95 panic("crypto/cipher: incorrect nonce length given to GCM")
96 }
97 // Sanity check to prevent the authentication from always succeeding if an
98 // implementation leaves tagSize uninitialized, for example.
99 if g.tagSize < gcmMinimumTagSize {
100 panic("crypto/cipher: incorrect GCM tag size")
101 }
102 103 if len(ciphertext) < g.tagSize {
104 return nil, errOpen
105 }
106 if uint64(len(ciphertext)) > uint64((1<<32)-2)*gcmBlockSize+uint64(g.tagSize) {
107 return nil, errOpen
108 }
109 110 ret, out := sliceForAppend(dst, len(ciphertext)-g.tagSize)
111 if alias.InexactOverlap(out, ciphertext) {
112 panic("crypto/cipher: invalid buffer overlap of output and input")
113 }
114 if alias.AnyOverlap(out, data) {
115 panic("crypto/cipher: invalid buffer overlap of output and additional data")
116 }
117 118 fips140.RecordApproved()
119 if err := open(out, g, nonce, ciphertext, data); err != nil {
120 // We sometimes decrypt and authenticate concurrently, so we overwrite
121 // dst in the event of a tag mismatch. To be consistent across platforms
122 // and to avoid releasing unauthenticated plaintext, we clear the buffer
123 // in the event of an error.
124 clear(out)
125 return nil, err
126 }
127 return ret, nil
128 }
129 130 // sliceForAppend takes a slice and a requested number of bytes. It returns a
131 // slice with the contents of the given slice followed by that many bytes and a
132 // second slice that aliases into it and contains only the extra bytes. If the
133 // original slice has sufficient capacity then no allocation is performed.
134 func sliceForAppend(in []byte, n int) (head, tail []byte) {
135 if total := len(in) + n; cap(in) >= total {
136 head = in[:total]
137 } else {
138 head = []byte{:total}
139 copy(head, in)
140 }
141 tail = head[len(in):]
142 return
143 }
144