...

Source file src/pkg/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