Fix off-by-1 bug in getCiphertextLimit when extra padding in use
note that block cipher extra padding is disabled by default
bug only in codepath for non-blocking usage
refactor related padding code for clarity
@@ -127,19 +127,18 @@ public int getCiphertextLimit(int plaintextLimit)
ciphertextLimit += blockSize;
}
- int maxPadding = useExtraPadding ? 255 : blockSize;
-
// Leave room for the MAC and (block-aligning) padding
+
+ ciphertextLimit += useExtraPadding ? 256 : blockSize;
+
if (encryptThenMAC)
{
- ciphertextLimit += maxPadding;
ciphertextLimit -= (ciphertextLimit % blockSize);
ciphertextLimit += macSize;
}
else
{
ciphertextLimit += macSize;
- ciphertextLimit += maxPadding;
ciphertextLimit -= (ciphertextLimit % blockSize);
}
@@ -153,12 +152,6 @@ public int getPlaintextLimit(int ciphertextLimit)
int plaintextLimit = ciphertextLimit;
- // An explicit IV consumes 1 block
- if (useExplicitIV)
- {
- plaintextLimit -= blockSize;
- }
-
// Leave room for the MAC, and require block-alignment
if (encryptThenMAC)
{
@@ -174,6 +167,12 @@ public int getPlaintextLimit(int ciphertextLimit)
// Minimum 1 byte of padding
--plaintextLimit;
+ // An explicit IV consumes 1 block
+ if (useExplicitIV)
+ {
+ plaintextLimit -= blockSize;
+ }
+
return plaintextLimit;
}
@@ -189,16 +188,16 @@ public int getPlaintextLimit(int ciphertextLimit)
enc_input_length += macSize;
}
- int padding_length = blockSize - 1 - (enc_input_length % blockSize);
+ int padding_length = blockSize - (enc_input_length % blockSize);
if (useExtraPadding)
{
// Add a random number of extra blocks worth of padding
- int maxExtraPadBlocks = (255 - padding_length) / blockSize;
+ int maxExtraPadBlocks = (256 - padding_length) / blockSize;
int actualExtraPadBlocks = chooseExtraPadBlocks(crypto.getSecureRandom(), maxExtraPadBlocks);
padding_length += actualExtraPadBlocks * blockSize;
}
- int totalSize = len + macSize + padding_length + 1;
+ int totalSize = len + macSize + padding_length;
if (useExplicitIV)
{
totalSize += blockSize;
@@ -229,9 +228,10 @@ public int getPlaintextLimit(int ciphertextLimit)
outOff += mac.length;
}
- for (int i = 0; i <= padding_length; i++)
+ byte padByte = (byte)(padding_length - 1);
+ for (int i = 0; i < padding_length; ++i)
{
- outBuf[outOff++] = (byte)padding_length;
+ outBuf[outOff++] = padByte;
}
encryptCipher.doFinal(outBuf, blocks_start, outOff - blocks_start, outBuf, blocks_start);
