summaryrefslogtreecommitdiff
path: root/src/pkg/crypto/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/crypto/cipher')
-rw-r--r--src/pkg/crypto/cipher/ocfb.go36
-rw-r--r--src/pkg/crypto/cipher/ocfb_test.go17
2 files changed, 41 insertions, 12 deletions
diff --git a/src/pkg/crypto/cipher/ocfb.go b/src/pkg/crypto/cipher/ocfb.go
index 43cb5a531..b2d877591 100644
--- a/src/pkg/crypto/cipher/ocfb.go
+++ b/src/pkg/crypto/cipher/ocfb.go
@@ -12,11 +12,21 @@ type ocfbEncrypter struct {
outUsed int
}
+// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
+// performed.
+type OCFBResyncOption bool
+
+const (
+ OCFBResync OCFBResyncOption = true
+ OCFBNoResync OCFBResyncOption = false
+)
+
// NewOCFBEncrypter returns a Stream which encrypts data with OpenPGP's cipher
// feedback mode using the given Block, and an initial amount of ciphertext.
// randData must be random bytes and be the same length as the Block's block
-// size.
-func NewOCFBEncrypter(block Block, randData []byte) (Stream, []byte) {
+// size. Resync determines if the "resynchronization step" from RFC 4880, 13.9
+// step 7 is performed. Different parts of OpenPGP vary on this point.
+func NewOCFBEncrypter(block Block, randData []byte, resync OCFBResyncOption) (Stream, []byte) {
blockSize := block.BlockSize()
if len(randData) != blockSize {
return nil, nil
@@ -38,7 +48,13 @@ func NewOCFBEncrypter(block Block, randData []byte) (Stream, []byte) {
prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
- block.Encrypt(x.fre, prefix[2:])
+ if resync {
+ block.Encrypt(x.fre, prefix[2:])
+ } else {
+ x.fre[0] = prefix[blockSize]
+ x.fre[1] = prefix[blockSize+1]
+ x.outUsed = 2
+ }
return x, prefix
}
@@ -64,8 +80,10 @@ type ocfbDecrypter struct {
// NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher
// feedback mode using the given Block. Prefix must be the first blockSize + 2
// bytes of the ciphertext, where blockSize is the Block's block size. If an
-// incorrect key is detected then nil is returned.
-func NewOCFBDecrypter(block Block, prefix []byte) Stream {
+// incorrect key is detected then nil is returned. Resync determines if the
+// "resynchronization step" from RFC 4880, 13.9 step 7 is performed. Different
+// parts of OpenPGP vary on this point.
+func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Stream {
blockSize := block.BlockSize()
if len(prefix) != blockSize+2 {
return nil
@@ -93,7 +111,13 @@ func NewOCFBDecrypter(block Block, prefix []byte) Stream {
return nil
}
- block.Encrypt(x.fre, prefix[2:])
+ if resync {
+ block.Encrypt(x.fre, prefix[2:])
+ } else {
+ x.fre[0] = prefix[blockSize]
+ x.fre[1] = prefix[blockSize+1]
+ x.outUsed = 2
+ }
return x
}
diff --git a/src/pkg/crypto/cipher/ocfb_test.go b/src/pkg/crypto/cipher/ocfb_test.go
index 289bb7c91..40938b589 100644
--- a/src/pkg/crypto/cipher/ocfb_test.go
+++ b/src/pkg/crypto/cipher/ocfb_test.go
@@ -11,29 +11,34 @@ import (
"testing"
)
-func TestOCFB(t *testing.T) {
+func testOCFB(t *testing.T, resync OCFBResyncOption) {
block, err := aes.NewCipher(commonKey128)
if err != nil {
t.Error(err)
return
}
- plaintext := []byte("this is the plaintext")
+ plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
randData := make([]byte, block.BlockSize())
rand.Reader.Read(randData)
- ocfb, prefix := NewOCFBEncrypter(block, randData)
+ ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
ciphertext := make([]byte, len(plaintext))
ocfb.XORKeyStream(ciphertext, plaintext)
- ocfbdec := NewOCFBDecrypter(block, prefix)
+ ocfbdec := NewOCFBDecrypter(block, prefix, resync)
if ocfbdec == nil {
- t.Error("NewOCFBDecrypter failed")
+ t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
return
}
plaintextCopy := make([]byte, len(plaintext))
ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
if !bytes.Equal(plaintextCopy, plaintext) {
- t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
}
}
+
+func TestOCFB(t *testing.T) {
+ testOCFB(t, OCFBNoResync)
+ testOCFB(t, OCFBResync)
+}