Const-time padding improvements
6 files changed, 47 insertions, 53 deletions
diff --git a/crypto/src/crypto/paddings/ISO10126d2Padding.cs b/crypto/src/crypto/paddings/ISO10126d2Padding.cs
index e132a62dd..92845f165 100644
--- a/crypto/src/crypto/paddings/ISO10126d2Padding.cs
+++ b/crypto/src/crypto/paddings/ISO10126d2Padding.cs
@@ -60,17 +60,17 @@ namespace Org.BouncyCastle.Crypto.Paddings
* return the number of pad bytes present in the block.
*/
public int PadCount(byte[] input)
- //throws InvalidCipherTextException
{
- int count = input[input.Length - 1] & 0xff;
+ int count = input[input.Length -1];
+ int position = input.Length - count;
- if (count > input.Length)
- {
+ // constant time version
+ int failed = (position | (count - 1)) >> 31;
+
+ if (failed != 0)
throw new InvalidCipherTextException("pad block corrupted");
- }
return count;
}
}
-
}
diff --git a/crypto/src/crypto/paddings/ISO7816d4Padding.cs b/crypto/src/crypto/paddings/ISO7816d4Padding.cs
index 016b25a81..533b9d421 100644
--- a/crypto/src/crypto/paddings/ISO7816d4Padding.cs
+++ b/crypto/src/crypto/paddings/ISO7816d4Padding.cs
@@ -58,22 +58,22 @@ namespace Org.BouncyCastle.Crypto.Paddings
/**
* return the number of pad bytes present in the block.
*/
- public int PadCount(
- byte[] input)
+ public int PadCount(byte[] input)
{
- int count = input.Length - 1;
-
- while (count > 0 && input[count] == 0)
+ int position = -1, still00Mask = -1;
+ int i = input.Length;
+ while (--i >= 0)
{
- count--;
+ int next = input[i];
+ int match00Mask = ((next ^ 0x00) - 1) >> 31;
+ int match80Mask = ((next ^ 0x80) - 1) >> 31;
+ position ^= (i ^ position) & (still00Mask & match80Mask);
+ still00Mask &= match00Mask;
}
-
- if (input[count] != (byte)0x80)
- {
+ if (position < 0)
throw new InvalidCipherTextException("pad block corrupted");
- }
- return input.Length - count;
+ return input.Length - position;
}
}
}
diff --git a/crypto/src/crypto/paddings/Pkcs7Padding.cs b/crypto/src/crypto/paddings/Pkcs7Padding.cs
index 11585647a..4c192fcdf 100644
--- a/crypto/src/crypto/paddings/Pkcs7Padding.cs
+++ b/crypto/src/crypto/paddings/Pkcs7Padding.cs
@@ -54,23 +54,21 @@ namespace Org.BouncyCastle.Crypto.Paddings
/**
* return the number of pad bytes present in the block.
*/
- public int PadCount(
- byte[] input)
+ public int PadCount(byte[] input)
{
byte countAsByte = input[input.Length - 1];
int count = countAsByte;
+ int position = input.Length - count;
- if (count < 1 || count > input.Length)
- throw new InvalidCipherTextException("pad block corrupted");
-
- for (int i = 2; i <= count; i++)
+ int failed = (position | (count - 1)) >> 31;
+ for (int i = 0; i < input.Length; ++i)
{
- if (input[input.Length - i] != countAsByte)
- throw new InvalidCipherTextException("pad block corrupted");
+ failed |= (input[i] ^ countAsByte) & ~((i - position) >> 31);
}
+ if (failed != 0)
+ throw new InvalidCipherTextException("pad block corrupted");
return count;
}
}
-
}
diff --git a/crypto/src/crypto/paddings/TbcPadding.cs b/crypto/src/crypto/paddings/TbcPadding.cs
index 74b64e8e1..8034dc8ba 100644
--- a/crypto/src/crypto/paddings/TbcPadding.cs
+++ b/crypto/src/crypto/paddings/TbcPadding.cs
@@ -65,15 +65,16 @@ namespace Org.BouncyCastle.Crypto.Paddings
/// <summary> return the number of pad bytes present in the block.</summary>
public virtual int PadCount(byte[] input)
{
- byte code = input[input.Length - 1];
-
- int index = input.Length - 1;
- while (index > 0 && input[index - 1] == code)
+ int i = input.Length;
+ int code = input[--i], count = 1, countingMask = -1;
+ while (--i >= 0)
{
- index--;
+ int next = input[i];
+ int matchMask = ((next ^ code) - 1) >> 31;
+ countingMask &= matchMask;
+ count -= countingMask;
}
-
- return input.Length - index;
+ return count;
}
}
}
diff --git a/crypto/src/crypto/paddings/X923Padding.cs b/crypto/src/crypto/paddings/X923Padding.cs
index cc1b52b3e..fc9668116 100644
--- a/crypto/src/crypto/paddings/X923Padding.cs
+++ b/crypto/src/crypto/paddings/X923Padding.cs
@@ -66,15 +66,14 @@ namespace Org.BouncyCastle.Crypto.Paddings
/**
* return the number of pad bytes present in the block.
*/
- public int PadCount(
- byte[] input)
+ public int PadCount(byte[] input)
{
- int count = input[input.Length - 1] & 0xff;
+ int count = input[input.Length - 1];
+ int position = input.Length - count;
- if (count > input.Length)
- {
+ int failed = (position | (count - 1)) >> 31;
+ if (failed != 0)
throw new InvalidCipherTextException("pad block corrupted");
- }
return count;
}
diff --git a/crypto/src/crypto/paddings/ZeroBytePadding.cs b/crypto/src/crypto/paddings/ZeroBytePadding.cs
index 0d55ca4c2..ab5f4a1a3 100644
--- a/crypto/src/crypto/paddings/ZeroBytePadding.cs
+++ b/crypto/src/crypto/paddings/ZeroBytePadding.cs
@@ -46,23 +46,19 @@ namespace Org.BouncyCastle.Crypto.Paddings
return added;
}
- /// <summary> return the number of pad bytes present in the block.</summary>
- public int PadCount(
- byte[] input)
+ /// <summary> return the number of pad bytes present in the block.</summary>
+ public int PadCount(byte[] input)
{
- int count = input.Length;
-
- while (count > 0)
+ int count = 0, still00Mask = -1;
+ int i = input.Length;
+ while (--i >= 0)
{
- if (input[count - 1] != 0)
- {
- break;
- }
-
- count--;
+ int next = input[i];
+ int match00Mask = ((next ^ 0x00) - 1) >> 31;
+ still00Mask &= match00Mask;
+ count -= still00Mask;
}
-
- return input.Length - count;
+ return count;
}
}
}
|