miscreant / meta

Meta-repository for Miscreant: misuse-resistant symmetric encryption library with AES-SIV (RFC 5297) and AES-PMAC-SIV support
https://miscreant.io
Other
474 stars 27 forks source link

[Go] Failure with in-place Seal/Open #173

Open conradoplg opened 6 years ago

conradoplg commented 6 years ago

According to Seal/Open documentations (and the cipher.AEAD interface), they should work when dst and plaintext (resp. ciphertext) overlap entirely.

However, that doesn't work. This test fails:

func TestAESCMACSIVInPlace(t *testing.T) {
    v := loadAESSIVExamples("aes_siv.tjson")[0]

    c, err := NewAESCMACSIV(v.key)
    if err != nil {
        t.Fatalf("NewAESCMACSIV: %s", err)
    }
    pt := make([]byte, len(v.plaintext), len(v.plaintext)+c.Overhead())
    copy(pt, v.plaintext)
    ct, err := c.Seal(pt[:0], pt, v.ad...)
    if err != nil {
        t.Errorf("Seal: %s", err)
    }
    if !bytes.Equal(v.ciphertext, ct) {
        t.Errorf("Seal: expected: %x\ngot: %x", v.ciphertext, ct)
    }

    copy(ct, v.ciphertext)
    pt, err = c.Open(ct[:0], ct, v.ad...)
    if err != nil {
        t.Errorf("Open: %s", err)
    }
    if !bytes.Equal(v.plaintext, pt) {
        t.Errorf("Open: expected: %x\ngot: %x", v.plaintext, pt)
    }
}

I can write a MR fixing this, however, since the tag comes before the ciphertext it seems that will require making a whole copy of the input in this case (since XORKeyStream alse requires its input to overlap entirely or not at all), entirely defeating the purpose of the in-place optimization. However, I don't see a way out without breaking the cipher.AEAD contract, or moving the tag after the ciphertext (#152)

What do you think?

conradoplg commented 6 years ago

There is another way to fix this: use copy which does support overlapped arguments to shuffle things around when doing in-place operations.

The two branches mentioned above implement the two strategies. Which one do you prefer, if you're going down this route?