Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle CBC padding #521

Closed
wants to merge 14 commits into from
46 changes: 36 additions & 10 deletions encfs/CipherFileIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,33 @@ int CipherFileIO::getAttr(struct stat *stbuf) const {
// stat() the backing file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message is missing for commit Padding, size !

int res = base->getAttr(stbuf);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change adds a few cases to the "if maze". Please simplify the whole thing a bit by doing

if(res != 0)
    return res;
if(!S_ISREG(stbuf->st_mode))
   // special files don't need size adjustment.
   return 0;
if(stbuf->st_size == 0)
    // empty files stay empty
   return 0;

here. In other words, handle the simple cases first and early return.

// adjust size if we have a file header
if ((res == 0) && haveHeader && S_ISREG(stbuf->st_mode) &&
(stbuf->st_size > 0)) {
// adjust size if we have a file header or padding
if ((res == 0) && S_ISREG(stbuf->st_mode)) {
if (!fsConfig->reverseEncryption) {
/* In normal mode, the upper file (plaintext) is smaller
* than the backing ciphertext file */
rAssert(stbuf->st_size >= HEADER_SIZE);
stbuf->st_size -= HEADER_SIZE;
} else {
if (haveHeader && (stbuf->st_size > 0)) {
/* Instead of using rAssert, we could also relax the rule and return 0.
* Think about a file which would have been partially written.
* Same for getSize() below. */
rAssert(stbuf->st_size >= HEADER_SIZE);
stbuf->st_size -= HEADER_SIZE;
}
if (haveCBCPadding && (stbuf->st_size > 0)) {
rAssert(stbuf->st_size >= fsConfig->cipher->cipherBlockSize());
stbuf->st_size -= fsConfig->cipher->cipherBlockSize();
stbuf->st_size -= stbuf->st_size / (blockSize() + 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is rounding of some kind? Needs a comment, or better, it's own function. In gocryptfs I have cipherSizeToPlainSize() and plainSizeToCipherSize().

}
} else if (stbuf->st_size > 0) {
if (haveCBCPadding) {
stbuf->st_size += (stbuf->st_size - 1) / (blockSize() - 1);
stbuf->st_size += fsConfig->cipher->cipherBlockSize();
}
/* In reverse mode, the upper file (ciphertext) is larger than
* the backing plaintext file */
stbuf->st_size += HEADER_SIZE;
if (haveHeader) {
stbuf->st_size += HEADER_SIZE;
}
}
}

Expand All @@ -194,11 +209,22 @@ off_t CipherFileIO::getSize() const {
off_t size = base->getSize();
// No check on S_ISREG here -- don't call getSize over getAttr unless this
// is a normal file!
if (haveHeader && size > 0) {
if (!fsConfig->reverseEncryption) {
if (!fsConfig->reverseEncryption) {
if (haveHeader && (size > 0)) {
rAssert(size >= HEADER_SIZE);
size -= HEADER_SIZE;
} else {
}
if (haveCBCPadding && (size > 0)) {
rAssert(size >= fsConfig->cipher->cipherBlockSize());
size -= fsConfig->cipher->cipherBlockSize();
size -= size / (blockSize() + 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the logic from getAttr(), right? Why?

}
} else if (size > 0) {
if (haveCBCPadding) {
size += (size - 1) / (blockSize() - 1);
size += fsConfig->cipher->cipherBlockSize();
}
if (haveHeader) {
size += HEADER_SIZE;
}
}
Expand Down