aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/ocfb.go')
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/ocfb.go143
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
7package packet
8
9import (
10 "crypto/cipher"
11)
12
13type 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.
21type OCFBResyncOption bool
22
23const (
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.
34func 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
66func (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
79type 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.
92func 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
131func (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}