Source file src/crypto/cipher/ofb.go

     1  // Copyright 2011 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  // OFB (Output Feedback) Mode.
     6  
     7  package cipher
     8  
     9  import "crypto/internal/subtle"
    10  
    11  type ofb struct {
    12  	b       Block
    13  	cipher  []byte
    14  	out     []byte
    15  	outUsed int
    16  }
    17  
    18  // NewOFB returns a Stream that encrypts or decrypts using the block cipher b
    19  // in output feedback mode. The initialization vector iv's length must be equal
    20  // to b's block size.
    21  func NewOFB(b Block, iv []byte) Stream {
    22  	blockSize := b.BlockSize()
    23  	if len(iv) != blockSize {
    24  		panic("cipher.NewOFB: IV length must equal block size")
    25  	}
    26  	bufSize := streamBufferSize
    27  	if bufSize < blockSize {
    28  		bufSize = blockSize
    29  	}
    30  	x := &ofb{
    31  		b:       b,
    32  		cipher:  make([]byte, blockSize),
    33  		out:     make([]byte, 0, bufSize),
    34  		outUsed: 0,
    35  	}
    36  
    37  	copy(x.cipher, iv)
    38  	return x
    39  }
    40  
    41  func (x *ofb) refill() {
    42  	bs := x.b.BlockSize()
    43  	remain := len(x.out) - x.outUsed
    44  	if remain > x.outUsed {
    45  		return
    46  	}
    47  	copy(x.out, x.out[x.outUsed:])
    48  	x.out = x.out[:cap(x.out)]
    49  	for remain < len(x.out)-bs {
    50  		x.b.Encrypt(x.cipher, x.cipher)
    51  		copy(x.out[remain:], x.cipher)
    52  		remain += bs
    53  	}
    54  	x.out = x.out[:remain]
    55  	x.outUsed = 0
    56  }
    57  
    58  func (x *ofb) XORKeyStream(dst, src []byte) {
    59  	if len(dst) < len(src) {
    60  		panic("crypto/cipher: output smaller than input")
    61  	}
    62  	if subtle.InexactOverlap(dst[:len(src)], src) {
    63  		panic("crypto/cipher: invalid buffer overlap")
    64  	}
    65  	for len(src) > 0 {
    66  		if x.outUsed >= len(x.out)-x.b.BlockSize() {
    67  			x.refill()
    68  		}
    69  		n := xorBytes(dst, src, x.out[x.outUsed:])
    70  		dst = dst[n:]
    71  		src = src[n:]
    72  		x.outUsed += n
    73  	}
    74  }
    75  

View as plain text