...

Source file src/crypto/cipher/ctr.go

Documentation: crypto/cipher

		 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