diff options
-rw-r--r-- | internal/contentenc/offsets.go | 15 |
1 files changed, 14 insertions, 1 deletions
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 |