]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/cipher: add resync open to OCFB mode.
authorAdam Langley <agl@golang.org>
Thu, 3 Feb 2011 14:17:42 +0000 (09:17 -0500)
committerAdam Langley <agl@golang.org>
Thu, 3 Feb 2011 14:17:42 +0000 (09:17 -0500)
OpenPGP changed its OCFB mode for more modern packets (for example, the
MDC symmetrically encrypted packet). This change adds a bool to
determine which mode is used.

R=bradfitzgo, r, rsc
CC=golang-dev
https://golang.org/cl/4126041

src/pkg/crypto/cipher/ocfb.go
src/pkg/crypto/cipher/ocfb_test.go

index 43cb5a53108334277eb63ccddabf31efb109a02b..b2d87759115cd132dd15344816c2daeb78762efa 100644 (file)
@@ -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
 }
 
index 289bb7c91e540f38cd827b60a580d1941578e036..7aae27bec910334d5be46a29a56c4812a80dd6e7 100644 (file)
@@ -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.Error("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)
+}