Skip to content

Commit

Permalink
Reuse ciphertext slice for plaintext when decrypting
Browse files Browse the repository at this point in the history
  • Loading branch information
twiss committed Dec 16, 2024
1 parent 6fa7f91 commit fee7824
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 22 deletions.
8 changes: 4 additions & 4 deletions internal/byteutil/byteutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ func ShiftNBytesLeft(dst, x []byte, n int) {
dst = append(dst, make([]byte, n/8)...)
}

// XorBytesMut assumes equal input length, replaces X with X XOR Y
// XorBytesMut replaces X with X XOR Y. len(X) must be >= len(Y).
func XorBytesMut(X, Y []byte) {
for i := 0; i < len(X); i++ {
for i := 0; i < len(Y); i++ {
X[i] ^= Y[i]
}
}

// XorBytes assumes equal input length, puts X XOR Y into Z
// XorBytes puts X XOR Y into Z. len(Z) and len(X) must be >= len(Y).
func XorBytes(Z, X, Y []byte) {
for i := 0; i < len(X); i++ {
for i := 0; i < len(Y); i++ {
Z[i] = X[i] ^ Y[i]
}
}
Expand Down
28 changes: 12 additions & 16 deletions ocb/ocb.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte {
panic("crypto/ocb: Incorrect nonce length given to OCB")
}
ret, out := byteutil.SliceForAppend(dst, len(plaintext)+o.tagSize)
o.crypt(enc, out, nonce, adata, plaintext)
tag := o.crypt(enc, out, nonce, adata, plaintext)
copy(out[len(plaintext):], tag)
return ret
}

Expand All @@ -122,12 +123,10 @@ func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
return nil, ocbError("Ciphertext shorter than tag length")
}
sep := len(ciphertext) - o.tagSize
ret, out := byteutil.SliceForAppend(dst, len(ciphertext))
ret, out := byteutil.SliceForAppend(dst, sep)
ciphertextData := ciphertext[:sep]
tag := ciphertext[sep:]
o.crypt(dec, out, nonce, adata, ciphertextData)
if subtle.ConstantTimeCompare(ret[sep:], tag) == 1 {
ret = ret[:sep]
tag := o.crypt(dec, out, nonce, adata, ciphertextData)
if subtle.ConstantTimeCompare(tag, ciphertext[sep:]) == 1 {
return ret, nil
}
for i := range out {
Expand All @@ -137,7 +136,8 @@ func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
}

// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt)
// function. It returns the resulting plain/ciphertext with the tag appended.
// function. It writes the resulting plain/ciphertext into Y and returns
// the tag.
func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
//
// Consider X as a sequence of 128-bit blocks
Expand Down Expand Up @@ -220,27 +220,23 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
// P_* || bit(1) || zeroes(127) - len(P_*)
switch instruction {
case enc:
paddedY := append(chunkX, byte(128))
paddedY = append(paddedY, make([]byte, blockSize-len(chunkX)-1)...)
byteutil.XorBytesMut(checksum, paddedY)
byteutil.XorBytesMut(checksum, chunkX)
checksum[len(chunkX)] ^= 128
case dec:
paddedX := append(chunkY, byte(128))
paddedX = append(paddedX, make([]byte, blockSize-len(chunkY)-1)...)
byteutil.XorBytesMut(checksum, paddedX)
byteutil.XorBytesMut(checksum, chunkY)
checksum[len(chunkY)] ^= 128
}
byteutil.XorBytes(tag, checksum, offset)
byteutil.XorBytesMut(tag, o.mask.lDol)
o.block.Encrypt(tag, tag)
byteutil.XorBytesMut(tag, o.hash(adata))
copy(Y[blockSize*m+len(chunkY):], tag[:o.tagSize])
} else {
byteutil.XorBytes(tag, checksum, offset)
byteutil.XorBytesMut(tag, o.mask.lDol)
o.block.Encrypt(tag, tag)
byteutil.XorBytesMut(tag, o.hash(adata))
copy(Y[blockSize*m:], tag[:o.tagSize])
}
return Y
return tag[:o.tagSize]
}

// This hash function is used to compute the tag. Per design, on empty input it
Expand Down
4 changes: 2 additions & 2 deletions openpgp/packet/aead_crypter.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
}

nonce := ar.computeNextNonce()
plainChunk, err := ar.aead.Open(nil, nonce, data, adata)
plainChunk, err := ar.aead.Open(data[:0:len(data)], nonce, data, adata)
if err != nil {
return nil, errors.ErrAEADTagVerification
}
Expand Down Expand Up @@ -243,7 +243,7 @@ func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
}

nonce := aw.computeNextNonce()
encrypted := aw.aead.Seal(nil, nonce, data, adata)
encrypted := aw.aead.Seal(data[:0:len(data)], nonce, data, adata)
aw.bytesProcessed += len(data)
if err := aw.aeadCrypter.incrementIndex(); err != nil {
return nil, err
Expand Down

0 comments on commit fee7824

Please sign in to comment.