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