diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/ocfb.go')
-rw-r--r-- | vendor/golang.org/x/crypto/openpgp/packet/ocfb.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go new file mode 100644 index 0000000..ce2a33a --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go | |||
@@ -0,0 +1,143 @@ | |||
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 | // OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 | ||
6 | |||
7 | package packet | ||
8 | |||
9 | import ( | ||
10 | "crypto/cipher" | ||
11 | ) | ||
12 | |||
13 | type ocfbEncrypter struct { | ||
14 | b cipher.Block | ||
15 | fre []byte | ||
16 | outUsed int | ||
17 | } | ||
18 | |||
19 | // An OCFBResyncOption determines if the "resynchronization step" of OCFB is | ||
20 | // performed. | ||
21 | type OCFBResyncOption bool | ||
22 | |||
23 | const ( | ||
24 | OCFBResync OCFBResyncOption = true | ||
25 | OCFBNoResync OCFBResyncOption = false | ||
26 | ) | ||
27 | |||
28 | // NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's | ||
29 | // cipher feedback mode using the given cipher.Block, and an initial amount of | ||
30 | // ciphertext. randData must be random bytes and be the same length as the | ||
31 | // cipher.Block's block size. Resync determines if the "resynchronization step" | ||
32 | // from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on | ||
33 | // this point. | ||
34 | func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { | ||
35 | blockSize := block.BlockSize() | ||
36 | if len(randData) != blockSize { | ||
37 | return nil, nil | ||
38 | } | ||
39 | |||
40 | x := &ocfbEncrypter{ | ||
41 | b: block, | ||
42 | fre: make([]byte, blockSize), | ||
43 | outUsed: 0, | ||
44 | } | ||
45 | prefix := make([]byte, blockSize+2) | ||
46 | |||
47 | block.Encrypt(x.fre, x.fre) | ||
48 | for i := 0; i < blockSize; i++ { | ||
49 | prefix[i] = randData[i] ^ x.fre[i] | ||
50 | } | ||
51 | |||
52 | block.Encrypt(x.fre, prefix[:blockSize]) | ||
53 | prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] | ||
54 | prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] | ||
55 | |||
56 | if resync { | ||
57 | block.Encrypt(x.fre, prefix[2:]) | ||
58 | } else { | ||
59 | x.fre[0] = prefix[blockSize] | ||
60 | x.fre[1] = prefix[blockSize+1] | ||
61 | x.outUsed = 2 | ||
62 | } | ||
63 | return x, prefix | ||
64 | } | ||
65 | |||
66 | func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { | ||
67 | for i := 0; i < len(src); i++ { | ||
68 | if x.outUsed == len(x.fre) { | ||
69 | x.b.Encrypt(x.fre, x.fre) | ||
70 | x.outUsed = 0 | ||
71 | } | ||
72 | |||
73 | x.fre[x.outUsed] ^= src[i] | ||
74 | dst[i] = x.fre[x.outUsed] | ||
75 | x.outUsed++ | ||
76 | } | ||
77 | } | ||
78 | |||
79 | type ocfbDecrypter struct { | ||
80 | b cipher.Block | ||
81 | fre []byte | ||
82 | outUsed int | ||
83 | } | ||
84 | |||
85 | // NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's | ||
86 | // cipher feedback mode using the given cipher.Block. Prefix must be the first | ||
87 | // blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's | ||
88 | // block size. If an incorrect key is detected then nil is returned. On | ||
89 | // successful exit, blockSize+2 bytes of decrypted data are written into | ||
90 | // prefix. Resync determines if the "resynchronization step" from RFC 4880, | ||
91 | // 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. | ||
92 | func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { | ||
93 | blockSize := block.BlockSize() | ||
94 | if len(prefix) != blockSize+2 { | ||
95 | return nil | ||
96 | } | ||
97 | |||
98 | x := &ocfbDecrypter{ | ||
99 | b: block, | ||
100 | fre: make([]byte, blockSize), | ||
101 | outUsed: 0, | ||
102 | } | ||
103 | prefixCopy := make([]byte, len(prefix)) | ||
104 | copy(prefixCopy, prefix) | ||
105 | |||
106 | block.Encrypt(x.fre, x.fre) | ||
107 | for i := 0; i < blockSize; i++ { | ||
108 | prefixCopy[i] ^= x.fre[i] | ||
109 | } | ||
110 | |||
111 | block.Encrypt(x.fre, prefix[:blockSize]) | ||
112 | prefixCopy[blockSize] ^= x.fre[0] | ||
113 | prefixCopy[blockSize+1] ^= x.fre[1] | ||
114 | |||
115 | if prefixCopy[blockSize-2] != prefixCopy[blockSize] || | ||
116 | prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { | ||
117 | return nil | ||
118 | } | ||
119 | |||
120 | if resync { | ||
121 | block.Encrypt(x.fre, prefix[2:]) | ||
122 | } else { | ||
123 | x.fre[0] = prefix[blockSize] | ||
124 | x.fre[1] = prefix[blockSize+1] | ||
125 | x.outUsed = 2 | ||
126 | } | ||
127 | copy(prefix, prefixCopy) | ||
128 | return x | ||
129 | } | ||
130 | |||
131 | func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { | ||
132 | for i := 0; i < len(src); i++ { | ||
133 | if x.outUsed == len(x.fre) { | ||
134 | x.b.Encrypt(x.fre, x.fre) | ||
135 | x.outUsed = 0 | ||
136 | } | ||
137 | |||
138 | c := src[i] | ||
139 | dst[i] = x.fre[x.outUsed] ^ src[i] | ||
140 | x.fre[x.outUsed] = c | ||
141 | x.outUsed++ | ||
142 | } | ||
143 | } | ||