1 // Copyright 2016 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.
11 subtleoverlap
"crypto/internal/subtle"
18 // This file contains two implementations of AES-GCM. The first implementation
19 // (gcmAsm) uses the KMCTR instruction to encrypt using AES in counter mode and
20 // the KIMD instruction for GHASH. The second implementation (gcmKMA) uses the
21 // newer KMA instruction which performs both operations.
23 // gcmCount represents a 16-byte big-endian count value.
24 type gcmCount
[16]byte
26 // inc increments the rightmost 32-bits of the count value by 1.
27 func (x
*gcmCount
) inc() {
28 binary
.BigEndian
.PutUint32(x
[len(x
)-4:], binary
.BigEndian
.Uint32(x
[len(x
)-4:])+1)
31 // gcmLengths writes len0 || len1 as big-endian values to a 16-byte array.
32 func gcmLengths(len0
, len1
uint64) [16]byte {
34 binary
.BigEndian
.PutUint64(v
[0:], len0
)
35 binary
.BigEndian
.PutUint64(v
[8:], len1
)
39 // gcmHashKey represents the 16-byte hash key required by the GHASH algorithm.
40 type gcmHashKey
[16]byte
52 gcmMinimumTagSize
= 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
53 gcmStandardNonceSize
= 12
56 var errOpen
= errors
.New("cipher: message authentication failed")
58 // Assert that aesCipherAsm implements the gcmAble interface.
59 var _ gcmAble
= (*aesCipherAsm
)(nil)
61 // NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only
62 // called by crypto/cipher.NewGCM via the gcmAble interface.
63 func (c
*aesCipherAsm
) NewGCM(nonceSize
, tagSize
int) (cipher
.AEAD
, error
) {
65 c
.Encrypt(hk
[:], hk
[:])
72 if cpu
.S390X
.HasAESGCM
{
79 func (g
*gcmAsm
) NonceSize() int {
83 func (g
*gcmAsm
) Overhead() int {
87 // sliceForAppend takes a slice and a requested number of bytes. It returns a
88 // slice with the contents of the given slice followed by that many bytes and a
89 // second slice that aliases into it and contains only the extra bytes. If the
90 // original slice has sufficient capacity then no allocation is performed.
91 func sliceForAppend(in
[]byte, n
int) (head
, tail
[]byte) {
92 if total
:= len(in
) + n
; cap(in
) >= total
{
95 head
= make([]byte, total
)
102 // ghash uses the GHASH algorithm to hash data with the given key. The initial
103 // hash value is given by hash which will be updated with the new hash value.
104 // The length of data must be a multiple of 16-bytes.
106 func ghash(key
*gcmHashKey
, hash
*[16]byte, data
[]byte)
108 // paddedGHASH pads data with zeroes until its length is a multiple of
109 // 16-bytes. It then calculates a new value for hash using the GHASH algorithm.
110 func (g
*gcmAsm
) paddedGHASH(hash
*[16]byte, data
[]byte) {
111 siz
:= len(data
) &^ 0xf // align size to 16-bytes
113 ghash(&g
.hashKey
, hash
, data
[:siz
])
119 ghash(&g
.hashKey
, hash
, s
[:])
123 // cryptBlocksGCM encrypts src using AES in counter mode using the given
124 // function code and key. The rightmost 32-bits of the counter are incremented
125 // between each block as required by the GCM spec. The initial counter value
126 // is given by cnt, which is updated with the value of the next counter value
129 // The lengths of both dst and buf must be greater than or equal to the length
130 // of src. buf may be partially or completely overwritten during the execution
133 func cryptBlocksGCM(fn code
, key
, dst
, src
, buf
[]byte, cnt
*gcmCount
)
135 // counterCrypt encrypts src using AES in counter mode and places the result
136 // into dst. cnt is the initial count value and will be updated with the next
137 // count value. The length of dst must be greater than or equal to the length
139 func (g
*gcmAsm
) counterCrypt(dst
, src
[]byte, cnt
*gcmCount
) {
140 // Copying src into a buffer improves performance on some models when
141 // src and dst point to the same underlying array. We also need a
142 // buffer for counter values.
143 var ctrbuf
, srcbuf
[2048]byte
146 if len(src
) > len(ctrbuf
) {
149 siz
&^= 0xf // align siz to 16-bytes
150 copy(srcbuf
[:], src
[:siz
])
151 cryptBlocksGCM(g
.block
.function
, g
.block
.key
, dst
[:siz
], srcbuf
[:siz
], ctrbuf
[:], cnt
)
157 g
.block
.Encrypt(x
[:], cnt
[:])
159 dst
[i
] = src
[i
] ^ x
[i
]
165 // deriveCounter computes the initial GCM counter state from the given nonce.
166 // See NIST SP 800-38D, section 7.1.
167 func (g
*gcmAsm
) deriveCounter(nonce
[]byte) gcmCount
{
168 // GCM has two modes of operation with respect to the initial counter
169 // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path"
170 // for nonces of other lengths. For a 96-bit nonce, the nonce, along
171 // with a four-byte big-endian counter starting at one, is used
172 // directly as the starting counter. For other nonce sizes, the counter
173 // is computed by passing it through the GHASH function.
175 if len(nonce
) == gcmStandardNonceSize
{
176 copy(counter
[:], nonce
)
177 counter
[gcmBlockSize
-1] = 1
180 g
.paddedGHASH(&hash
, nonce
)
181 lens
:= gcmLengths(0, uint64(len(nonce
))*8)
182 g
.paddedGHASH(&hash
, lens
[:])
183 copy(counter
[:], hash
[:])
188 // auth calculates GHASH(ciphertext, additionalData), masks the result with
189 // tagMask and writes the result to out.
190 func (g
*gcmAsm
) auth(out
, ciphertext
, additionalData
[]byte, tagMask
*[gcmTagSize
]byte) {
192 g
.paddedGHASH(&hash
, additionalData
)
193 g
.paddedGHASH(&hash
, ciphertext
)
194 lens
:= gcmLengths(uint64(len(additionalData
))*8, uint64(len(ciphertext
))*8)
195 g
.paddedGHASH(&hash
, lens
[:])
203 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
205 func (g
*gcmAsm
) Seal(dst
, nonce
, plaintext
, data
[]byte) []byte {
206 if len(nonce
) != g
.nonceSize
{
207 panic("crypto/cipher: incorrect nonce length given to GCM")
209 if uint64(len(plaintext
)) > ((1<<32)-2)*BlockSize
{
210 panic("crypto/cipher: message too large for GCM")
213 ret
, out
:= sliceForAppend(dst
, len(plaintext
)+g
.tagSize
)
214 if subtleoverlap
.InexactOverlap(out
[:len(plaintext
)], plaintext
) {
215 panic("crypto/cipher: invalid buffer overlap")
218 counter
:= g
.deriveCounter(nonce
)
220 var tagMask
[gcmBlockSize
]byte
221 g
.block
.Encrypt(tagMask
[:], counter
[:])
224 var tagOut
[gcmTagSize
]byte
225 g
.counterCrypt(out
, plaintext
, &counter
)
226 g
.auth(tagOut
[:], out
[:len(plaintext
)], data
, &tagMask
)
227 copy(out
[len(plaintext
):], tagOut
[:])
232 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
234 func (g
*gcmAsm
) Open(dst
, nonce
, ciphertext
, data
[]byte) ([]byte, error
) {
235 if len(nonce
) != g
.nonceSize
{
236 panic("crypto/cipher: incorrect nonce length given to GCM")
238 // Sanity check to prevent the authentication from always succeeding if an implementation
239 // leaves tagSize uninitialized, for example.
240 if g
.tagSize
< gcmMinimumTagSize
{
241 panic("crypto/cipher: incorrect GCM tag size")
243 if len(ciphertext
) < g
.tagSize
{
246 if uint64(len(ciphertext
)) > ((1<<32)-2)*uint64(BlockSize
)+uint64(g
.tagSize
) {
250 tag
:= ciphertext
[len(ciphertext
)-g
.tagSize
:]
251 ciphertext
= ciphertext
[:len(ciphertext
)-g
.tagSize
]
253 counter
:= g
.deriveCounter(nonce
)
255 var tagMask
[gcmBlockSize
]byte
256 g
.block
.Encrypt(tagMask
[:], counter
[:])
259 var expectedTag
[gcmTagSize
]byte
260 g
.auth(expectedTag
[:], ciphertext
, data
, &tagMask
)
262 ret
, out
:= sliceForAppend(dst
, len(ciphertext
))
263 if subtleoverlap
.InexactOverlap(out
, ciphertext
) {
264 panic("crypto/cipher: invalid buffer overlap")
267 if subtle
.ConstantTimeCompare(expectedTag
[:g
.tagSize
], tag
) != 1 {
268 // The AESNI code decrypts and authenticates concurrently, and
269 // so overwrites dst in the event of a tag mismatch. That
270 // behavior is mimicked here in order to be consistent across
278 g
.counterCrypt(out
, ciphertext
, &counter
)
282 // gcmKMA implements the cipher.AEAD interface using the KMA instruction. It should
283 // only be used if hasKMA is true.
288 // flags for the KMA instruction
290 kmaHS
= 1 << 10 // hash subkey supplied
291 kmaLAAD
= 1 << 9 // last series of additional authenticated data
292 kmaLPC
= 1 << 8 // last series of plaintext or ciphertext blocks
293 kmaDecrypt
= 1 << 7 // decrypt
296 // kmaGCM executes the encryption or decryption operation given by fn. The tag
297 // will be calculated and written to tag. cnt should contain the current
298 // counter state and will be overwritten with the updated counter state.
299 // TODO(mundaym): could pass in hash subkey
301 func kmaGCM(fn code
, key
, dst
, src
, aad
[]byte, tag
*[16]byte, cnt
*gcmCount
)
303 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
305 func (g
*gcmKMA
) Seal(dst
, nonce
, plaintext
, data
[]byte) []byte {
306 if len(nonce
) != g
.nonceSize
{
307 panic("crypto/cipher: incorrect nonce length given to GCM")
309 if uint64(len(plaintext
)) > ((1<<32)-2)*BlockSize
{
310 panic("crypto/cipher: message too large for GCM")
313 ret
, out
:= sliceForAppend(dst
, len(plaintext
)+g
.tagSize
)
314 if subtleoverlap
.InexactOverlap(out
[:len(plaintext
)], plaintext
) {
315 panic("crypto/cipher: invalid buffer overlap")
318 counter
:= g
.deriveCounter(nonce
)
319 fc
:= g
.block
.function | kmaLAAD | kmaLPC
321 var tag
[gcmTagSize
]byte
322 kmaGCM(fc
, g
.block
.key
, out
[:len(plaintext
)], plaintext
, data
, &tag
, &counter
)
323 copy(out
[len(plaintext
):], tag
[:])
328 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
330 func (g
*gcmKMA
) Open(dst
, nonce
, ciphertext
, data
[]byte) ([]byte, error
) {
331 if len(nonce
) != g
.nonceSize
{
332 panic("crypto/cipher: incorrect nonce length given to GCM")
334 if len(ciphertext
) < g
.tagSize
{
337 if uint64(len(ciphertext
)) > ((1<<32)-2)*uint64(BlockSize
)+uint64(g
.tagSize
) {
341 tag
:= ciphertext
[len(ciphertext
)-g
.tagSize
:]
342 ciphertext
= ciphertext
[:len(ciphertext
)-g
.tagSize
]
343 ret
, out
:= sliceForAppend(dst
, len(ciphertext
))
344 if subtleoverlap
.InexactOverlap(out
, ciphertext
) {
345 panic("crypto/cipher: invalid buffer overlap")
348 if g
.tagSize
< gcmMinimumTagSize
{
349 panic("crypto/cipher: incorrect GCM tag size")
352 counter
:= g
.deriveCounter(nonce
)
353 fc
:= g
.block
.function | kmaLAAD | kmaLPC | kmaDecrypt
355 var expectedTag
[gcmTagSize
]byte
356 kmaGCM(fc
, g
.block
.key
, out
[:len(ciphertext
)], ciphertext
, data
, &expectedTag
, &counter
)
358 if subtle
.ConstantTimeCompare(expectedTag
[:g
.tagSize
], tag
) != 1 {
359 // The AESNI code decrypts and authenticates concurrently, and
360 // so overwrites dst in the event of a tag mismatch. That
361 // behavior is mimicked here in order to be consistent across