...
Run Format

Source file src/crypto/aes/ctr_s390x.go

Documentation: crypto/aes

  // Copyright 2016 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package aes
  
  import (
  	"crypto/cipher"
  	"unsafe"
  )
  
  // Assert that aesCipherAsm implements the ctrAble interface.
  var _ ctrAble = (*aesCipherAsm)(nil)
  
  // xorBytes xors the contents of a and b and places the resulting values into
  // dst. If a and b are not the same length then the number of bytes processed
  // will be equal to the length of shorter of the two. Returns the number
  // of bytes processed.
  //go:noescape
  func xorBytes(dst, a, b []byte) int
  
  // streamBufferSize is the number of bytes of encrypted counter values to cache.
  const streamBufferSize = 32 * BlockSize
  
  type aesctr struct {
  	block   *aesCipherAsm          // block cipher
  	ctr     [2]uint64              // next value of the counter (big endian)
  	buffer  []byte                 // buffer for the encrypted counter values
  	storage [streamBufferSize]byte // array backing buffer slice
  }
  
  // NewCTR returns a Stream which encrypts/decrypts using the AES block
  // cipher in counter mode. The length of iv must be the same as BlockSize.
  func (c *aesCipherAsm) NewCTR(iv []byte) cipher.Stream {
  	if len(iv) != BlockSize {
  		panic("cipher.NewCTR: IV length must equal block size")
  	}
  	var ac aesctr
  	ac.block = c
  	ac.ctr[0] = *(*uint64)(unsafe.Pointer((&iv[0]))) // high bits
  	ac.ctr[1] = *(*uint64)(unsafe.Pointer((&iv[8]))) // low bits
  	ac.buffer = ac.storage[:0]
  	return &ac
  }
  
  func (c *aesctr) refill() {
  	// Fill up the buffer with an incrementing count.
  	c.buffer = c.storage[:streamBufferSize]
  	c0, c1 := c.ctr[0], c.ctr[1]
  	for i := 0; i < streamBufferSize; i += BlockSize {
  		b0 := (*uint64)(unsafe.Pointer(&c.buffer[i]))
  		b1 := (*uint64)(unsafe.Pointer(&c.buffer[i+BlockSize/2]))
  		*b0, *b1 = c0, c1
  		// Increment in big endian: c0 is high, c1 is low.
  		c1++
  		if c1 == 0 {
  			// add carry
  			c0++
  		}
  	}
  	c.ctr[0], c.ctr[1] = c0, c1
  	// Encrypt the buffer using AES in ECB mode.
  	cryptBlocks(c.block.function, &c.block.key[0], &c.buffer[0], &c.buffer[0], streamBufferSize)
  }
  
  func (c *aesctr) XORKeyStream(dst, src []byte) {
  	for len(src) > 0 {
  		if len(c.buffer) == 0 {
  			c.refill()
  		}
  		n := xorBytes(dst, src, c.buffer)
  		c.buffer = c.buffer[n:]
  		src = src[n:]
  		dst = dst[n:]
  	}
  }
  

View as plain text