Source file src/crypto/aes/ctr_s390x.go

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

View as plain text