...

Source file src/crypto/cipher/ctr.go

     1	// Copyright 2009 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	// Counter (CTR) mode.
     6	
     7	// CTR converts a block cipher into a stream cipher by
     8	// repeatedly encrypting an incrementing counter and
     9	// xoring the resulting stream of data with the input.
    10	
    11	// See NIST SP 800-38A, pp 13-15
    12	
    13	package cipher
    14	
    15	import "crypto/internal/subtle"
    16	
    17	type ctr struct {
    18		b       Block
    19		ctr     []byte
    20		out     []byte
    21		outUsed int
    22	}
    23	
    24	const streamBufferSize = 512
    25	
    26	// ctrAble is an interface implemented by ciphers that have a specific optimized
    27	// implementation of CTR, like crypto/aes. NewCTR will check for this interface
    28	// and return the specific Stream if found.
    29	type ctrAble interface {
    30		NewCTR(iv []byte) Stream
    31	}
    32	
    33	// NewCTR returns a Stream which encrypts/decrypts using the given Block in
    34	// counter mode. The length of iv must be the same as the Block's block size.
    35	func NewCTR(block Block, iv []byte) Stream {
    36		if ctr, ok := block.(ctrAble); ok {
    37			return ctr.NewCTR(iv)
    38		}
    39		if len(iv) != block.BlockSize() {
    40			panic("cipher.NewCTR: IV length must equal block size")
    41		}
    42		bufSize := streamBufferSize
    43		if bufSize < block.BlockSize() {
    44			bufSize = block.BlockSize()
    45		}
    46		return &ctr{
    47			b:       block,
    48			ctr:     dup(iv),
    49			out:     make([]byte, 0, bufSize),
    50			outUsed: 0,
    51		}
    52	}
    53	
    54	func (x *ctr) refill() {
    55		remain := len(x.out) - x.outUsed
    56		copy(x.out, x.out[x.outUsed:])
    57		x.out = x.out[:cap(x.out)]
    58		bs := x.b.BlockSize()
    59		for remain <= len(x.out)-bs {
    60			x.b.Encrypt(x.out[remain:], x.ctr)
    61			remain += bs
    62	
    63			// Increment counter
    64			for i := len(x.ctr) - 1; i >= 0; i-- {
    65				x.ctr[i]++
    66				if x.ctr[i] != 0 {
    67					break
    68				}
    69			}
    70		}
    71		x.out = x.out[:remain]
    72		x.outUsed = 0
    73	}
    74	
    75	func (x *ctr) XORKeyStream(dst, src []byte) {
    76		if len(dst) < len(src) {
    77			panic("crypto/cipher: output smaller than input")
    78		}
    79		if subtle.InexactOverlap(dst[:len(src)], src) {
    80			panic("crypto/cipher: invalid buffer overlap")
    81		}
    82		for len(src) > 0 {
    83			if x.outUsed >= len(x.out)-x.b.BlockSize() {
    84				x.refill()
    85			}
    86			n := xorBytes(dst, src, x.out[x.outUsed:])
    87			dst = dst[n:]
    88			src = src[n:]
    89			x.outUsed += n
    90		}
    91	}
    92	

View as plain text