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

View as plain text