github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/crypto/aes/ctr_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 "unsafe" 10 ) 11 12 // Assert that aesCipherAsm implements the ctrAble interface. 13 var _ ctrAble = (*aesCipherAsm)(nil) 14 15 // xorBytes xors the contents of a and b and places the resulting values into 16 // dst. If a and b are not the same length then the number of bytes processed 17 // will be equal to the length of shorter of the two. Returns the number 18 // of bytes processed. 19 //go:noescape 20 func xorBytes(dst, a, b []byte) int 21 22 // streamBufferSize is the number of bytes of encrypted counter values to cache. 23 const streamBufferSize = 32 * BlockSize 24 25 type aesctr struct { 26 block *aesCipherAsm // block cipher 27 ctr [2]uint64 // next value of the counter (big endian) 28 buffer []byte // buffer for the encrypted counter values 29 storage [streamBufferSize]byte // array backing buffer slice 30 } 31 32 // NewCTR returns a Stream which encrypts/decrypts using the AES block 33 // cipher in counter mode. The length of iv must be the same as BlockSize. 34 func (c *aesCipherAsm) NewCTR(iv []byte) cipher.Stream { 35 if len(iv) != BlockSize { 36 panic("cipher.NewCTR: IV length must equal block size") 37 } 38 var ac aesctr 39 ac.block = c 40 ac.ctr[0] = *(*uint64)(unsafe.Pointer((&iv[0]))) // high bits 41 ac.ctr[1] = *(*uint64)(unsafe.Pointer((&iv[8]))) // low bits 42 ac.buffer = ac.storage[:0] 43 return &ac 44 } 45 46 func (c *aesctr) refill() { 47 // Fill up the buffer with an incrementing count. 48 c.buffer = c.storage[:streamBufferSize] 49 c0, c1 := c.ctr[0], c.ctr[1] 50 for i := 0; i < streamBufferSize; i += BlockSize { 51 b0 := (*uint64)(unsafe.Pointer(&c.buffer[i])) 52 b1 := (*uint64)(unsafe.Pointer(&c.buffer[i+BlockSize/2])) 53 *b0, *b1 = c0, c1 54 // Increment in big endian: c0 is high, c1 is low. 55 c1++ 56 if c1 == 0 { 57 // add carry 58 c0++ 59 } 60 } 61 c.ctr[0], c.ctr[1] = c0, c1 62 // Encrypt the buffer using AES in ECB mode. 63 cryptBlocks(c.block.function, &c.block.key[0], &c.buffer[0], &c.buffer[0], streamBufferSize) 64 } 65 66 func (c *aesctr) XORKeyStream(dst, src []byte) { 67 for len(src) > 0 { 68 if len(c.buffer) == 0 { 69 c.refill() 70 } 71 n := xorBytes(dst, src, c.buffer) 72 c.buffer = c.buffer[n:] 73 src = src[n:] 74 dst = dst[n:] 75 } 76 }