aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/primitives/padding.py36
1 files changed, 30 insertions, 6 deletions
diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py
index eac18c2a..34bdfd89 100644
--- a/cryptography/hazmat/primitives/padding.py
+++ b/cryptography/hazmat/primitives/padding.py
@@ -11,11 +11,36 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import cffi
+
import six
+from six.moves import xrange
from cryptography.hazmat.primitives import interfaces
+_ffi = cffi.FFI()
+_ffi.cdef("""
+unsigned int Cryptography_constant_time_lt(unsigned int, unsigned int);
+""")
+_lib = _ffi.verify("""
+/* Returns the value of the input with the most-significant-bit copied to all
+ of the bits. This relies on implementation details of computers with 2's
+ complement representations of integers, which is not required by the C
+ standard. */
+static unsigned int Cryptography_DUPLICATE_MSB_TO_ALL(unsigned int a) {
+ return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
+}
+
+/* This returns 0xFF if a < b else 0x00, but does so in a constant time
+ fashion */
+unsigned int Cryptography_constant_time_lt(unsigned int a, unsigned int b) {
+ a -= b;
+ return Cryptography_DUPLICATE_MSB_TO_ALL(a);
+}
+""")
+
+
class PKCS7(object):
def __init__(self, block_size):
super(PKCS7, self).__init__()
@@ -106,14 +131,13 @@ class _PKCS7UnpaddingContext(object):
pad_size = six.indexbytes(self._buffer, -1)
- if not (0 < pad_size <= self.block_size // 8):
- raise ValueError("Invalid padding bytes")
-
mismatch = 0
- for b in six.iterbytes(self._buffer[-pad_size:]):
- mismatch |= b ^ pad_size
+ for i in xrange(self.block_size // 8):
+ mask = _lib.Cryptography_constant_time_lt(i, pad_size)
+ b = six.indexbytes(self._buffer, self.block_size // 8 - 1 - i)
+ mismatch |= (mask & (pad_size ^ b))
- if mismatch != 0:
+ if mismatch != 0 or not (0 < pad_size <= self.block_size // 8):
raise ValueError("Invalid padding bytes")
res = self._buffer[:-pad_size]