Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / crypto / cipher / cfb.go
1 // Copyright 2010 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 // CFB (Cipher Feedback) Mode.
6
7 package cipher
8
9 type cfb struct {
10         b       Block
11         out     []byte
12         outUsed int
13         decrypt bool
14 }
15
16 // NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
17 // using the given Block. The iv must be the same length as the Block's block
18 // size.
19 func NewCFBEncrypter(block Block, iv []byte) Stream {
20         if len(iv) != block.BlockSize() {
21                 panic("cipher.NewCBFEncrypter: IV length must equal block size")
22         }
23         return newCFB(block, iv, false)
24 }
25
26 // NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
27 // using the given Block. The iv must be the same length as the Block's block
28 // size.
29 func NewCFBDecrypter(block Block, iv []byte) Stream {
30         if len(iv) != block.BlockSize() {
31                 panic("cipher.NewCBFEncrypter: IV length must equal block size")
32         }
33         return newCFB(block, iv, true)
34 }
35
36 func newCFB(block Block, iv []byte, decrypt bool) Stream {
37         blockSize := block.BlockSize()
38         if len(iv) != blockSize {
39                 return nil
40         }
41
42         x := &cfb{
43                 b:       block,
44                 out:     make([]byte, blockSize),
45                 outUsed: 0,
46                 decrypt: decrypt,
47         }
48         block.Encrypt(x.out, iv)
49
50         return x
51 }
52
53 func (x *cfb) XORKeyStream(dst, src []byte) {
54         for i := 0; i < len(src); i++ {
55                 if x.outUsed == len(x.out) {
56                         x.b.Encrypt(x.out, x.out)
57                         x.outUsed = 0
58                 }
59
60                 if x.decrypt {
61                         t := src[i]
62                         dst[i] = src[i] ^ x.out[x.outUsed]
63                         x.out[x.outUsed] = t
64                 } else {
65                         x.out[x.outUsed] ^= src[i]
66                         dst[i] = x.out[x.outUsed]
67                 }
68                 x.outUsed++
69         }
70 }