PR c++/86342 - -Wdeprecated-copy and system headers.
[official-gcc.git] / libgo / go / crypto / aes / gcm_s390x.go
blobba6d7ce766534033ec9ff93d7f8075e1b8a5b6ae
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.
5 // +build ignore
7 package aes
9 import (
10 "crypto/cipher"
11 "crypto/subtle"
12 "errors"
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
27 n += 1
28 x[12] = byte(n >> 24)
29 x[13] = byte(n >> 16)
30 x[14] = byte(n >> 8)
31 x[15] = byte(n)
34 // gcmLengths writes len0 || len1 as big-endian values to a 16-byte array.
35 func gcmLengths(len0, len1 uint64) [16]byte {
36 return [16]byte{
37 byte(len0 >> 56),
38 byte(len0 >> 48),
39 byte(len0 >> 40),
40 byte(len0 >> 32),
41 byte(len0 >> 24),
42 byte(len0 >> 16),
43 byte(len0 >> 8),
44 byte(len0),
45 byte(len1 >> 56),
46 byte(len1 >> 48),
47 byte(len1 >> 40),
48 byte(len1 >> 32),
49 byte(len1 >> 24),
50 byte(len1 >> 16),
51 byte(len1 >> 8),
52 byte(len1),
56 // gcmHashKey represents the 16-byte hash key required by the GHASH algorithm.
57 type gcmHashKey [16]byte
59 type gcmAsm struct {
60 block *aesCipherAsm
61 hashKey gcmHashKey
62 nonceSize int
65 const (
66 gcmBlockSize = 16
67 gcmTagSize = 16
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) {
79 var hk gcmHashKey
80 c.Encrypt(hk[:], hk[:])
81 g := gcmAsm{
82 block: c,
83 hashKey: hk,
84 nonceSize: nonceSize,
86 if hasKMA {
87 g := gcmKMA{g}
88 return &g, nil
90 return &g, nil
93 func (g *gcmAsm) NonceSize() int {
94 return g.nonceSize
97 func (*gcmAsm) Overhead() int {
98 return gcmTagSize
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 {
107 head = in[:total]
108 } else {
109 head = make([]byte, total)
110 copy(head, in)
112 tail = head[len(in):]
113 return
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.
119 //go:noescape
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
126 if siz > 0 {
127 ghash(&g.hashKey, hash, data[:siz])
128 data = data[siz:]
130 if len(data) > 0 {
131 var s [16]byte
132 copy(s[:], data)
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
141 // to use.
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
145 // of the function.
146 //go:noescape
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
152 // of src.
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
158 for len(src) >= 16 {
159 siz := len(src)
160 if len(src) > len(ctrbuf) {
161 siz = 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)
166 src = src[siz:]
167 dst = dst[siz:]
169 if len(src) > 0 {
170 var x [16]byte
171 g.block.Encrypt(x[:], cnt[:])
172 for i := range src {
173 dst[i] = src[i] ^ x[i]
175 cnt.inc()
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.
188 var counter gcmCount
189 if len(nonce) == gcmStandardNonceSize {
190 copy(counter[:], nonce)
191 counter[gcmBlockSize-1] = 1
192 } else {
193 var hash [16]byte
194 g.paddedGHASH(&hash, nonce)
195 lens := gcmLengths(0, uint64(len(nonce))*8)
196 g.paddedGHASH(&hash, lens[:])
197 copy(counter[:], hash[:])
199 return counter
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) {
205 var hash [16]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[:])
211 copy(out, hash[:])
212 for i := range out {
213 out[i] ^= tagMask[i]
217 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
218 // details.
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[:])
233 counter.inc()
235 g.counterCrypt(out, plaintext, &counter)
236 g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask)
238 return ret
241 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
242 // for details.
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 {
248 return nil, errOpen
250 if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize {
251 return nil, errOpen
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[:])
261 counter.inc()
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
272 // platforms.
273 for i := range out {
274 out[i] = 0
276 return nil, errOpen
279 g.counterCrypt(out, ciphertext, &counter)
280 return ret, nil
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.
292 type gcmKMA struct {
293 gcmAsm
296 // flags for the KMA instruction
297 const (
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
308 //go:noescape
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
312 // details.
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[:])
330 return ret
333 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
334 // for details.
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 {
340 return nil, errOpen
342 if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize {
343 return nil, errOpen
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
360 // platforms.
361 for i := range out {
362 out[i] = 0
364 return nil, errOpen
367 return ret, nil