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