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  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  }
    84  

View as plain text