github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/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  }