summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-08-25 13:08:01 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-08-25 13:08:01 +0700
commit2753922dff3e341f66c8bc3852e6eeec70827e1e (patch)
tree53473c56b9f6311b284fe9244bee6b1e246108ea
parentadded EncapsulationLength property (diff)
downloadBouncyCastle.NET-ed25519-2753922dff3e341f66c8bc3852e6eeec70827e1e.tar.xz
Const-time padding improvements
-rw-r--r--crypto/src/crypto/paddings/ISO10126d2Padding.cs12
-rw-r--r--crypto/src/crypto/paddings/ISO7816d4Padding.cs22
-rw-r--r--crypto/src/crypto/paddings/Pkcs7Padding.cs16
-rw-r--r--crypto/src/crypto/paddings/TbcPadding.cs15
-rw-r--r--crypto/src/crypto/paddings/X923Padding.cs11
-rw-r--r--crypto/src/crypto/paddings/ZeroBytePadding.cs24
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;
         }
     }
 }