github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/src/crypto/aes/gcm_s390x.go (about) 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. 4 5 package aes 6 7 import ( 8 "crypto/cipher" 9 "crypto/subtle" 10 "errors" 11 ) 12 13 // This file contains two implementations of AES-GCM. The first implementation 14 // (gcmAsm) uses the KMCTR instruction to encrypt using AES in counter mode and 15 // the KIMD instruction for GHASH. The second implementation (gcmKMA) uses the 16 // newer KMA instruction which performs both operations. 17 18 // gcmCount represents a 16-byte big-endian count value. 19 type gcmCount [16]byte 20 21 // inc increments the rightmost 32-bits of the count value by 1. 22 func (x *gcmCount) inc() { 23 // The compiler should optimize this to a 32-bit addition. 24 n := uint32(x[15]) | uint32(x[14])<<8 | uint32(x[13])<<16 | uint32(x[12])<<24 25 n += 1 26 x[12] = byte(n >> 24) 27 x[13] = byte(n >> 16) 28 x[14] = byte(n >> 8) 29 x[15] = byte(n) 30 } 31 32 // gcmLengths writes len0 || len1 as big-endian values to a 16-byte array. 33 func gcmLengths(len0, len1 uint64) [16]byte { 34 return [16]byte{ 35 byte(len0 >> 56), 36 byte(len0 >> 48), 37 byte(len0 >> 40), 38 byte(len0 >> 32), 39 byte(len0 >> 24), 40 byte(len0 >> 16), 41 byte(len0 >> 8), 42 byte(len0), 43 byte(len1 >> 56), 44 byte(len1 >> 48), 45 byte(len1 >> 40), 46 byte(len1 >> 32), 47 byte(len1 >> 24), 48 byte(len1 >> 16), 49 byte(len1 >> 8), 50 byte(len1), 51 } 52 } 53 54 // gcmHashKey represents the 16-byte hash key required by the GHASH algorithm. 55 type gcmHashKey [16]byte 56 57 type gcmAsm struct { 58 block *aesCipherAsm 59 hashKey gcmHashKey 60 nonceSize int 61 tagSize int 62 } 63 64 const ( 65 gcmBlockSize = 16 66 gcmTagSize = 16 67 gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. 68 gcmStandardNonceSize = 12 69 ) 70 71 var errOpen = errors.New("cipher: message authentication failed") 72 73 // Assert that aesCipherAsm implements the gcmAble interface. 74 var _ gcmAble = (*aesCipherAsm)(nil) 75 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, tagSize 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, 85 tagSize: tagSize, 86 } 87 if hasKMA { 88 g := gcmKMA{g} 89 return &g, nil 90 } 91 return &g, nil 92 } 93 94 func (g *gcmAsm) NonceSize() int { 95 return g.nonceSize 96 } 97 98 func (g *gcmAsm) Overhead() int { 99 return g.tagSize 100 } 101 102 // sliceForAppend takes a slice and a requested number of bytes. It returns a 103 // slice with the contents of the given slice followed by that many bytes and a 104 // second slice that aliases into it and contains only the extra bytes. If the 105 // original slice has sufficient capacity then no allocation is performed. 106 func sliceForAppend(in []byte, n int) (head, tail []byte) { 107 if total := len(in) + n; cap(in) >= total { 108 head = in[:total] 109 } else { 110 head = make([]byte, total) 111 copy(head, in) 112 } 113 tail = head[len(in):] 114 return 115 } 116 117 // ghash uses the GHASH algorithm to hash data with the given key. The initial 118 // hash value is given by hash which will be updated with the new hash value. 119 // The length of data must be a multiple of 16-bytes. 120 //go:noescape 121 func ghash(key *gcmHashKey, hash *[16]byte, data []byte) 122 123 // paddedGHASH pads data with zeroes until its length is a multiple of 124 // 16-bytes. It then calculates a new value for hash using the GHASH algorithm. 125 func (g *gcmAsm) paddedGHASH(hash *[16]byte, data []byte) { 126 siz := len(data) &^ 0xf // align size to 16-bytes 127 if siz > 0 { 128 ghash(&g.hashKey, hash, data[:siz]) 129 data = data[siz:] 130 } 131 if len(data) > 0 { 132 var s [16]byte 133 copy(s[:], data) 134 ghash(&g.hashKey, hash, s[:]) 135 } 136 } 137 138 // cryptBlocksGCM encrypts src using AES in counter mode using the given 139 // function code and key. The rightmost 32-bits of the counter are incremented 140 // between each block as required by the GCM spec. The initial counter value 141 // is given by cnt, which is updated with the value of the next counter value 142 // to use. 143 // 144 // The lengths of both dst and buf must be greater than or equal to the length 145 // of src. buf may be partially or completely overwritten during the execution 146 // of the function. 147 //go:noescape 148 func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *gcmCount) 149 150 // counterCrypt encrypts src using AES in counter mode and places the result 151 // into dst. cnt is the initial count value and will be updated with the next 152 // count value. The length of dst must be greater than or equal to the length 153 // of src. 154 func (g *gcmAsm) counterCrypt(dst, src []byte, cnt *gcmCount) { 155 // Copying src into a buffer improves performance on some models when 156 // src and dst point to the same underlying array. We also need a 157 // buffer for counter values. 158 var ctrbuf, srcbuf [2048]byte 159 for len(src) >= 16 { 160 siz := len(src) 161 if len(src) > len(ctrbuf) { 162 siz = len(ctrbuf) 163 } 164 siz &^= 0xf // align siz to 16-bytes 165 copy(srcbuf[:], src[:siz]) 166 cryptBlocksGCM(g.block.function, g.block.key, dst[:siz], srcbuf[:siz], ctrbuf[:], cnt) 167 src = src[siz:] 168 dst = dst[siz:] 169 } 170 if len(src) > 0 { 171 var x [16]byte 172 g.block.Encrypt(x[:], cnt[:]) 173 for i := range src { 174 dst[i] = src[i] ^ x[i] 175 } 176 cnt.inc() 177 } 178 } 179 180 // deriveCounter computes the initial GCM counter state from the given nonce. 181 // See NIST SP 800-38D, section 7.1. 182 func (g *gcmAsm) deriveCounter(nonce []byte) gcmCount { 183 // GCM has two modes of operation with respect to the initial counter 184 // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path" 185 // for nonces of other lengths. For a 96-bit nonce, the nonce, along 186 // with a four-byte big-endian counter starting at one, is used 187 // directly as the starting counter. For other nonce sizes, the counter 188 // is computed by passing it through the GHASH function. 189 var counter gcmCount 190 if len(nonce) == gcmStandardNonceSize { 191 copy(counter[:], nonce) 192 counter[gcmBlockSize-1] = 1 193 } else { 194 var hash [16]byte 195 g.paddedGHASH(&hash, nonce) 196 lens := gcmLengths(0, uint64(len(nonce))*8) 197 g.paddedGHASH(&hash, lens[:]) 198 copy(counter[:], hash[:]) 199 } 200 return counter 201 } 202 203 // auth calculates GHASH(ciphertext, additionalData), masks the result with 204 // tagMask and writes the result to out. 205 func (g *gcmAsm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) { 206 var hash [16]byte 207 g.paddedGHASH(&hash, additionalData) 208 g.paddedGHASH(&hash, ciphertext) 209 lens := gcmLengths(uint64(len(additionalData))*8, uint64(len(ciphertext))*8) 210 g.paddedGHASH(&hash, lens[:]) 211 212 copy(out, hash[:]) 213 for i := range out { 214 out[i] ^= tagMask[i] 215 } 216 } 217 218 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for 219 // details. 220 func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { 221 if len(nonce) != g.nonceSize { 222 panic("cipher: incorrect nonce length given to GCM") 223 } 224 if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { 225 panic("cipher: message too large for GCM") 226 } 227 228 ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) 229 230 counter := g.deriveCounter(nonce) 231 232 var tagMask [gcmBlockSize]byte 233 g.block.Encrypt(tagMask[:], counter[:]) 234 counter.inc() 235 236 var tagOut [gcmTagSize]byte 237 g.counterCrypt(out, plaintext, &counter) 238 g.auth(tagOut[:], out[:len(plaintext)], data, &tagMask) 239 copy(out[len(plaintext):], tagOut[:]) 240 241 return ret 242 } 243 244 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface 245 // for details. 246 func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { 247 if len(nonce) != g.nonceSize { 248 panic("cipher: incorrect nonce length given to GCM") 249 } 250 // Sanity check to prevent the authentication from always succeeding if an implementation 251 // leaves tagSize uninitialized, for example. 252 if g.tagSize < gcmMinimumTagSize { 253 panic("cipher: incorrect GCM tag size") 254 } 255 if len(ciphertext) < g.tagSize { 256 return nil, errOpen 257 } 258 if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { 259 return nil, errOpen 260 } 261 262 tag := ciphertext[len(ciphertext)-g.tagSize:] 263 ciphertext = ciphertext[:len(ciphertext)-g.tagSize] 264 265 counter := g.deriveCounter(nonce) 266 267 var tagMask [gcmBlockSize]byte 268 g.block.Encrypt(tagMask[:], counter[:]) 269 counter.inc() 270 271 var expectedTag [gcmTagSize]byte 272 g.auth(expectedTag[:], ciphertext, data, &tagMask) 273 274 ret, out := sliceForAppend(dst, len(ciphertext)) 275 276 if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { 277 // The AESNI code decrypts and authenticates concurrently, and 278 // so overwrites dst in the event of a tag mismatch. That 279 // behavior is mimicked here in order to be consistent across 280 // platforms. 281 for i := range out { 282 out[i] = 0 283 } 284 return nil, errOpen 285 } 286 287 g.counterCrypt(out, ciphertext, &counter) 288 return ret, nil 289 } 290 291 // supportsKMA reports whether the message-security-assist 8 facility is available. 292 // This function call may be expensive so hasKMA should be queried instead. 293 func supportsKMA() bool 294 295 // hasKMA contains the result of supportsKMA. 296 var hasKMA = supportsKMA() 297 298 // gcmKMA implements the cipher.AEAD interface using the KMA instruction. It should 299 // only be used if hasKMA is true. 300 type gcmKMA struct { 301 gcmAsm 302 } 303 304 // flags for the KMA instruction 305 const ( 306 kmaHS = 1 << 10 // hash subkey supplied 307 kmaLAAD = 1 << 9 // last series of additional authenticated data 308 kmaLPC = 1 << 8 // last series of plaintext or ciphertext blocks 309 kmaDecrypt = 1 << 7 // decrypt 310 ) 311 312 // kmaGCM executes the encryption or decryption operation given by fn. The tag 313 // will be calculated and written to tag. cnt should contain the current 314 // counter state and will be overwritten with the updated counter state. 315 // TODO(mundaym): could pass in hash subkey 316 //go:noescape 317 func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount) 318 319 // Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for 320 // details. 321 func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte { 322 if len(nonce) != g.nonceSize { 323 panic("cipher: incorrect nonce length given to GCM") 324 } 325 if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { 326 panic("cipher: message too large for GCM") 327 } 328 329 ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) 330 331 counter := g.deriveCounter(nonce) 332 fc := g.block.function | kmaLAAD | kmaLPC 333 334 var tag [gcmTagSize]byte 335 kmaGCM(fc, g.block.key, out[:len(plaintext)], plaintext, data, &tag, &counter) 336 copy(out[len(plaintext):], tag[:]) 337 338 return ret 339 } 340 341 // Open authenticates and decrypts ciphertext. See the cipher.AEAD interface 342 // for details. 343 func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { 344 if len(nonce) != g.nonceSize { 345 panic("cipher: incorrect nonce length given to GCM") 346 } 347 if len(ciphertext) < g.tagSize { 348 return nil, errOpen 349 } 350 if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { 351 return nil, errOpen 352 } 353 354 tag := ciphertext[len(ciphertext)-g.tagSize:] 355 ciphertext = ciphertext[:len(ciphertext)-g.tagSize] 356 ret, out := sliceForAppend(dst, len(ciphertext)) 357 358 if g.tagSize < gcmMinimumTagSize { 359 panic("cipher: incorrect GCM tag size") 360 } 361 362 counter := g.deriveCounter(nonce) 363 fc := g.block.function | kmaLAAD | kmaLPC | kmaDecrypt 364 365 var expectedTag [gcmTagSize]byte 366 kmaGCM(fc, g.block.key, out[:len(ciphertext)], ciphertext, data, &expectedTag, &counter) 367 368 if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { 369 // The AESNI code decrypts and authenticates concurrently, and 370 // so overwrites dst in the event of a tag mismatch. That 371 // behavior is mimicked here in order to be consistent across 372 // platforms. 373 for i := range out { 374 out[i] = 0 375 } 376 return nil, errOpen 377 } 378 379 return ret, nil 380 }