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.
15 // This file contains two implementations of AES-GCM. The first implementation
16 // (gcmAsm) uses the KMCTR instruction to encrypt using AES in counter mode and
17 // the KIMD instruction for GHASH. The second implementation (gcmKMA) uses the
18 // newer KMA instruction which performs both operations.
20 // gcmCount represents a 16-byte big-endian count value.
21 type gcmCount
[16]byte
23 // inc increments the rightmost 32-bits of the count value by 1.
24 func (x
*gcmCount
) inc() {
25 // The compiler should optimize this to a 32-bit addition.
26 n
:= uint32(x
[15]) |
uint32(x
[14])<<8 |
uint32(x
[13])<<16 |
uint32(x
[12])<<24
34 // gcmLengths writes len0 || len1 as big-endian values to a 16-byte array.
35 func gcmLengths(len0
, len1
uint64) [16]byte {
56 // gcmHashKey represents the 16-byte hash key required by the GHASH algorithm.
57 type gcmHashKey
[16]byte
68 gcmStandardNonceSize
= 12
71 var errOpen
= errors
.New("cipher: message authentication failed")
73 // Assert that aesCipherAsm implements the gcmAble interface.
74 var _ gcmAble
= (*aesCipherAsm
)(nil)
76 // NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only
77 // called by crypto/cipher.NewGCM via the gcmAble interface.
78 func (c
*aesCipherAsm
) NewGCM(nonceSize
int) (cipher
.AEAD
, error
) {
80 c
.Encrypt(hk
[:], hk
[:])
93 func (g
*gcmAsm
) NonceSize() int {
97 func (*gcmAsm
) Overhead() int {
101 // sliceForAppend takes a slice and a requested number of bytes. It returns a
102 // slice with the contents of the given slice followed by that many bytes and a
103 // second slice that aliases into it and contains only the extra bytes. If the
104 // original slice has sufficient capacity then no allocation is performed.
105 func sliceForAppend(in
[]byte, n
int) (head
, tail
[]byte) {
106 if total
:= len(in
) + n
; cap(in
) >= total
{
109 head
= make([]byte, total
)
112 tail
= head
[len(in
):]
116 // ghash uses the GHASH algorithm to hash data with the given key. The initial
117 // hash value is given by hash which will be updated with the new hash value.
118 // The length of data must be a multiple of 16-bytes.
120 func ghash(key
*gcmHashKey
, hash
*[16]byte, data
[]byte)
122 // paddedGHASH pads data with zeroes until its length is a multiple of
123 // 16-bytes. It then calculates a new value for hash using the GHASH algorithm.
124 func (g
*gcmAsm
) paddedGHASH(hash
*[16]byte, data
[]byte) {
125 siz
:= len(data
) &^ 0xf // align size to 16-bytes
127 ghash(&g
.hashKey
, hash
, data
[:siz
])
133 ghash(&g
.hashKey
, hash
, s
[:])
137 // cryptBlocksGCM encrypts src using AES in counter mode using the given
138 // function code and key. The rightmost 32-bits of the counter are incremented
139 // between each block as required by the GCM spec. The initial counter value
140 // is given by cnt, which is updated with the value of the next counter value
143 // The lengths of both dst and buf must be greater than or equal to the length
144 // of src. buf may be partially or completely overwritten during the execution
147 func cryptBlocksGCM(fn code
, key
, dst
, src
, buf
[]byte, cnt
*gcmCount
)
149 // counterCrypt encrypts src using AES in counter mode and places the result
150 // into dst. cnt is the initial count value and will be updated with the next
151 // count value. The length of dst must be greater than or equal to the length
153 func (g
*gcmAsm
) counterCrypt(dst
, src
[]byte, cnt
*gcmCount
) {
154 // Copying src into a buffer improves performance on some models when
155 // src and dst point to the same underlying array. We also need a
156 // buffer for counter values.
157 var ctrbuf
, srcbuf
[2048]byte
160 if len(src
) > len(ctrbuf
) {
163 siz
&^= 0xf // align siz to 16-bytes
164 copy(srcbuf
[:], src
[:siz
])
165 cryptBlocksGCM(g
.block
.function
, g
.block
.key
, dst
[:siz
], srcbuf
[:siz
], ctrbuf
[:], cnt
)
171 g
.block
.Encrypt(x
[:], cnt
[:])
173 dst
[i
] = src
[i
] ^ x
[i
]
179 // deriveCounter computes the initial GCM counter state from the given nonce.
180 // See NIST SP 800-38D, section 7.1.
181 func (g
*gcmAsm
) deriveCounter(nonce
[]byte) gcmCount
{
182 // GCM has two modes of operation with respect to the initial counter
183 // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path"
184 // for nonces of other lengths. For a 96-bit nonce, the nonce, along
185 // with a four-byte big-endian counter starting at one, is used
186 // directly as the starting counter. For other nonce sizes, the counter
187 // is computed by passing it through the GHASH function.
189 if len(nonce
) == gcmStandardNonceSize
{
190 copy(counter
[:], nonce
)
191 counter
[gcmBlockSize
-1] = 1
194 g
.paddedGHASH(&hash
, nonce
)
195 lens
:= gcmLengths(0, uint64(len(nonce
))*8)
196 g
.paddedGHASH(&hash
, lens
[:])
197 copy(counter
[:], hash
[:])
202 // auth calculates GHASH(ciphertext, additionalData), masks the result with
203 // tagMask and writes the result to out.
204 func (g
*gcmAsm
) auth(out
, ciphertext
, additionalData
[]byte, tagMask
*[gcmTagSize
]byte) {
206 g
.paddedGHASH(&hash
, additionalData
)
207 g
.paddedGHASH(&hash
, ciphertext
)
208 lens
:= gcmLengths(uint64(len(additionalData
))*8, uint64(len(ciphertext
))*8)
209 g
.paddedGHASH(&hash
, lens
[:])
217 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
219 func (g
*gcmAsm
) Seal(dst
, nonce
, plaintext
, data
[]byte) []byte {
220 if len(nonce
) != g
.nonceSize
{
221 panic("cipher: incorrect nonce length given to GCM")
223 if uint64(len(plaintext
)) > ((1<<32)-2)*BlockSize
{
224 panic("cipher: message too large for GCM")
227 ret
, out
:= sliceForAppend(dst
, len(plaintext
)+gcmTagSize
)
229 counter
:= g
.deriveCounter(nonce
)
231 var tagMask
[gcmBlockSize
]byte
232 g
.block
.Encrypt(tagMask
[:], counter
[:])
235 g
.counterCrypt(out
, plaintext
, &counter
)
236 g
.auth(out
[len(plaintext
):], out
[:len(plaintext
)], data
, &tagMask
)
241 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
243 func (g
*gcmAsm
) Open(dst
, nonce
, ciphertext
, data
[]byte) ([]byte, error
) {
244 if len(nonce
) != g
.nonceSize
{
245 panic("cipher: incorrect nonce length given to GCM")
247 if len(ciphertext
) < gcmTagSize
{
250 if uint64(len(ciphertext
)) > ((1<<32)-2)*BlockSize
+gcmTagSize
{
254 tag
:= ciphertext
[len(ciphertext
)-gcmTagSize
:]
255 ciphertext
= ciphertext
[:len(ciphertext
)-gcmTagSize
]
257 counter
:= g
.deriveCounter(nonce
)
259 var tagMask
[gcmBlockSize
]byte
260 g
.block
.Encrypt(tagMask
[:], counter
[:])
263 var expectedTag
[gcmTagSize
]byte
264 g
.auth(expectedTag
[:], ciphertext
, data
, &tagMask
)
266 ret
, out
:= sliceForAppend(dst
, len(ciphertext
))
268 if subtle
.ConstantTimeCompare(expectedTag
[:], tag
) != 1 {
269 // The AESNI code decrypts and authenticates concurrently, and
270 // so overwrites dst in the event of a tag mismatch. That
271 // behavior is mimicked here in order to be consistent across
279 g
.counterCrypt(out
, ciphertext
, &counter
)
283 // supportsKMA reports whether the message-security-assist 8 facility is available.
284 // This function call may be expensive so hasKMA should be queried instead.
285 func supportsKMA() bool
287 // hasKMA contains the result of supportsKMA.
288 var hasKMA
= supportsKMA()
290 // gcmKMA implements the cipher.AEAD interface using the KMA instruction. It should
291 // only be used if hasKMA is true.
296 // flags for the KMA instruction
298 kmaHS
= 1 << 10 // hash subkey supplied
299 kmaLAAD
= 1 << 9 // last series of additional authenticated data
300 kmaLPC
= 1 << 8 // last series of plaintext or ciphertext blocks
301 kmaDecrypt
= 1 << 7 // decrypt
304 // kmaGCM executes the encryption or decryption operation given by fn. The tag
305 // will be calculated and written to tag. cnt should contain the current
306 // counter state and will be overwritten with the updated counter state.
307 // TODO(mundaym): could pass in hash subkey
309 func kmaGCM(fn code
, key
, dst
, src
, aad
[]byte, tag
*[16]byte, cnt
*gcmCount
)
311 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
313 func (g
*gcmKMA
) Seal(dst
, nonce
, plaintext
, data
[]byte) []byte {
314 if len(nonce
) != g
.nonceSize
{
315 panic("cipher: incorrect nonce length given to GCM")
317 if uint64(len(plaintext
)) > ((1<<32)-2)*BlockSize
{
318 panic("cipher: message too large for GCM")
321 ret
, out
:= sliceForAppend(dst
, len(plaintext
)+gcmTagSize
)
323 counter
:= g
.deriveCounter(nonce
)
324 fc
:= g
.block
.function | kmaLAAD | kmaLPC
326 var tag
[gcmTagSize
]byte
327 kmaGCM(fc
, g
.block
.key
, out
[:len(plaintext
)], plaintext
, data
, &tag
, &counter
)
328 copy(out
[len(plaintext
):], tag
[:])
333 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
335 func (g
*gcmKMA
) Open(dst
, nonce
, ciphertext
, data
[]byte) ([]byte, error
) {
336 if len(nonce
) != g
.nonceSize
{
337 panic("cipher: incorrect nonce length given to GCM")
339 if len(ciphertext
) < gcmTagSize
{
342 if uint64(len(ciphertext
)) > ((1<<32)-2)*BlockSize
+gcmTagSize
{
346 tag
:= ciphertext
[len(ciphertext
)-gcmTagSize
:]
347 ciphertext
= ciphertext
[:len(ciphertext
)-gcmTagSize
]
348 ret
, out
:= sliceForAppend(dst
, len(ciphertext
))
350 counter
:= g
.deriveCounter(nonce
)
351 fc
:= g
.block
.function | kmaLAAD | kmaLPC | kmaDecrypt
353 var expectedTag
[gcmTagSize
]byte
354 kmaGCM(fc
, g
.block
.key
, out
[:len(ciphertext
)], ciphertext
, data
, &expectedTag
, &counter
)
356 if subtle
.ConstantTimeCompare(expectedTag
[:], tag
) != 1 {
357 // The AESNI code decrypts and authenticates concurrently, and
358 // so overwrites dst in the event of a tag mismatch. That
359 // behavior is mimicked here in order to be consistent across