LEFT | RIGHT |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package cipher | 5 package cipher |
6 | 6 |
7 import ( | 7 import ( |
8 "crypto/subtle" | 8 "crypto/subtle" |
9 "errors" | 9 "errors" |
10 ) | 10 ) |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 } | 256 } |
257 | 257 |
258 // gcmInc32 treats the final four bytes of counterBlock as a big-endian value | 258 // gcmInc32 treats the final four bytes of counterBlock as a big-endian value |
259 // and increments it. | 259 // and increments it. |
260 func gcmInc32(counterBlock *[16]byte) { | 260 func gcmInc32(counterBlock *[16]byte) { |
261 c := 1 | 261 c := 1 |
262 for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- { | 262 for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- { |
263 c += int(counterBlock[i]) | 263 c += int(counterBlock[i]) |
264 counterBlock[i] = byte(c) | 264 counterBlock[i] = byte(c) |
265 c >>= 8 | 265 c >>= 8 |
266 // must be constant time? | |
267 } | 266 } |
268 } | 267 } |
269 | 268 |
270 // sliceForAppend takes a slice and a requested number of bytes. It returns a | 269 // sliceForAppend takes a slice and a requested number of bytes. It returns a |
271 // slice with the contents of the given slice followed by that many bytes and a | 270 // slice with the contents of the given slice followed by that many bytes and a |
272 // second slice that aliases into it and contains only the extra bytes. If the | 271 // second slice that aliases into it and contains only the extra bytes. If the |
273 // original slice has sufficient capacity then no allocation is performed. | 272 // original slice has sufficient capacity then no allocation is performed. |
274 func sliceForAppend(in []byte, n int) (head, tail []byte) { | 273 func sliceForAppend(in []byte, n int) (head, tail []byte) { |
275 if total := len(in) + n; cap(in) >= total { | 274 if total := len(in) + n; cap(in) >= total { |
276 head = in[:total] | 275 head = in[:total] |
277 } else { | 276 } else { |
278 head = make([]byte, total) | 277 head = make([]byte, total) |
279 copy(head, in) | 278 copy(head, in) |
280 } | 279 } |
281 tail = head[len(in):] | 280 tail = head[len(in):] |
282 return | 281 return |
283 } | 282 } |
284 | 283 |
285 // counterCrypt crypts in to out using g.cipher in counter mode. | 284 // counterCrypt crypts in to out using g.cipher in counter mode. |
286 func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { | 285 func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { |
287 var mask [gcmBlockSize]byte | 286 var mask [gcmBlockSize]byte |
288 | 287 |
289 for len(in) >= gcmBlockSize { | 288 for len(in) >= gcmBlockSize { |
290 g.cipher.Encrypt(mask[:], counter[:]) | 289 g.cipher.Encrypt(mask[:], counter[:]) |
291 gcmInc32(counter) | 290 gcmInc32(counter) |
292 | 291 |
293 » » xor16Byte(out, in, mask[:]) | 292 » » xorWords(out, in, mask[:]) |
294 out = out[gcmBlockSize:] | 293 out = out[gcmBlockSize:] |
295 in = in[gcmBlockSize:] | 294 in = in[gcmBlockSize:] |
296 } | 295 } |
297 | 296 |
298 if len(in) > 0 { | 297 if len(in) > 0 { |
299 g.cipher.Encrypt(mask[:], counter[:]) | 298 g.cipher.Encrypt(mask[:], counter[:]) |
300 gcmInc32(counter) | 299 gcmInc32(counter) |
301 » » xor16Byte(out, in, mask[:]) | 300 » » xorBytes(out, in, mask[:]) |
302 } | 301 } |
303 } | 302 } |
304 | 303 |
305 // auth calculates GHASH(ciphertext, additionalData), masks the result with | 304 // auth calculates GHASH(ciphertext, additionalData), masks the result with |
306 // tagMask and writes the result to out. | 305 // tagMask and writes the result to out. |
307 func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]
byte) { | 306 func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]
byte) { |
308 var y gcmFieldElement | 307 var y gcmFieldElement |
309 g.update(&y, additionalData) | 308 g.update(&y, additionalData) |
310 g.update(&y, ciphertext) | 309 g.update(&y, ciphertext) |
311 | 310 |
312 y.low ^= uint64(len(additionalData)) * 8 | 311 y.low ^= uint64(len(additionalData)) * 8 |
313 y.high ^= uint64(len(ciphertext)) * 8 | 312 y.high ^= uint64(len(ciphertext)) * 8 |
314 | 313 |
315 g.mul(&y) | 314 g.mul(&y) |
316 | 315 |
317 putUint64(out, y.low) | 316 putUint64(out, y.low) |
318 putUint64(out[8:], y.high) | 317 putUint64(out[8:], y.high) |
319 | 318 |
320 » xor16Byte(out, out, tagMask[:]) | 319 » xorWords(out, out, tagMask[:]) |
321 } | 320 } |
322 | 321 |
323 func getUint64(data []byte) uint64 { | 322 func getUint64(data []byte) uint64 { |
324 r := uint64(data[0])<<56 | | 323 r := uint64(data[0])<<56 | |
325 uint64(data[1])<<48 | | 324 uint64(data[1])<<48 | |
326 uint64(data[2])<<40 | | 325 uint64(data[2])<<40 | |
327 uint64(data[3])<<32 | | 326 uint64(data[3])<<32 | |
328 uint64(data[4])<<24 | | 327 uint64(data[4])<<24 | |
329 uint64(data[5])<<16 | | 328 uint64(data[5])<<16 | |
330 uint64(data[6])<<8 | | 329 uint64(data[6])<<8 | |
331 uint64(data[7]) | 330 uint64(data[7]) |
332 return r | 331 return r |
333 } | 332 } |
334 | 333 |
335 func putUint64(out []byte, v uint64) { | 334 func putUint64(out []byte, v uint64) { |
336 out[0] = byte(v >> 56) | 335 out[0] = byte(v >> 56) |
337 out[1] = byte(v >> 48) | 336 out[1] = byte(v >> 48) |
338 out[2] = byte(v >> 40) | 337 out[2] = byte(v >> 40) |
339 out[3] = byte(v >> 32) | 338 out[3] = byte(v >> 32) |
340 out[4] = byte(v >> 24) | 339 out[4] = byte(v >> 24) |
341 out[5] = byte(v >> 16) | 340 out[5] = byte(v >> 16) |
342 out[6] = byte(v >> 8) | 341 out[6] = byte(v >> 8) |
343 out[7] = byte(v) | 342 out[7] = byte(v) |
344 } | 343 } |
LEFT | RIGHT |