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/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  }
    85  

View as plain text