From b4794bedecbddfd90c2a018825a798d2989a2838 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 26 May 2021 09:08:52 +0200 Subject: [PATCH] contentenc: fix CipherSizeToPlainSize non-monoticity For an illegal cipherSize, pretend we have an additional 1-byte block. See code comment for details. --- internal/contentenc/offsets.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/contentenc/offsets.go b/internal/contentenc/offsets.go index fdeb583..7487baf 100644 --- a/internal/contentenc/offsets.go +++ b/internal/contentenc/offsets.go @@ -31,7 +31,11 @@ func (be *ContentEnc) BlockNoToPlainOff(blockNo uint64) uint64 { return blockNo * be.plainBS } -// CipherSizeToPlainSize calculates the plaintext size from a ciphertext size +// CipherSizeToPlainSize calculates the plaintext size `plainSize` from a +// ciphertext size `cipherSize` (in bytes). +// +// Not all ciphertext sizes are legal due to the per-block overheads. +// For an illegal cipherSize, we return a best guess plainSize. func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 { // Zero-sized files stay zero-sized if cipherSize == 0 { @@ -49,6 +53,15 @@ func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 { return 0 } + // If the last block is incomplete, pad it to 1 byte of plaintext + // (= 33 bytes of ciphertext). + lastBlockSize := (cipherSize - HeaderLen) % be.cipherBS + if lastBlockSize > 0 && lastBlockSize <= be.BlockOverhead() { + tmp := cipherSize - lastBlockSize + be.BlockOverhead() + 1 + tlog.Warn.Printf("cipherSize %d: incomplete last block (%d bytes), padding to %d bytes", cipherSize, lastBlockSize, tmp) + cipherSize = tmp + } + // Block number at last byte blockNo := be.CipherOffToBlockNo(cipherSize - 1) blockCount := blockNo + 1