Constant-time utilities
authorEmilia Kasper <emilia@openssl.org>
Thu, 28 Aug 2014 13:33:34 +0000 (15:33 +0200)
committerEmilia Kasper <emilia@openssl.org>
Thu, 28 Aug 2014 14:26:01 +0000 (16:26 +0200)
Pull constant-time methods out to a separate header, add tests.

Reviewed-by: Bodo Moeller <bodo@openssl.org>
(cherry picked from commit 5a3d21c0585064292bde5cd34089e120487ab687)

Conflicts:
ssl/s3_cbc.c
test/Makefile

crypto/Makefile
crypto/constant_time_locl.h [new file with mode: 0644]
crypto/constant_time_test.c [new file with mode: 0644]
ssl/Makefile
ssl/s3_cbc.c
test/Makefile

index 5f6a06421622b3426fa0b80a0574fa1d2dbf5a0d..4ace5bc43f5f2dd654de0241886aed6b39adadd0 100644 (file)
@@ -31,6 +31,7 @@ CPUID_OBJ=mem_clr.o
 LIBS=
 
 GENERAL=Makefile README crypto-lib.com install.com
+TEST=constant_time_test.c
 
 LIB= $(TOP)/libcrypto.a
 SHARED_LIB= libcrypto$(SHLIB_EXT)
diff --git a/crypto/constant_time_locl.h b/crypto/constant_time_locl.h
new file mode 100644 (file)
index 0000000..782da6c
--- /dev/null
@@ -0,0 +1,169 @@
+/* crypto/constant_time_locl.h */
+/*
+ * Utilities for constant-time cryptography.
+ *
+ * Author: Emilia Kasper (emilia@openssl.org)
+ * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
+ * (Google).
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONSTANT_TIME_LOCL_H
+#define HEADER_CONSTANT_TIME_LOCL_H
+
+#include "e_os.h"  /* For 'inline' */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following methods return a bitmask of all ones (0xff...f) for true
+ * and 0 for false. This is useful for choosing a value based on the result
+ * of a conditional in constant time. For example,
+ *
+ * if (a < b) {
+ *   c = a;
+ * } else {
+ *   c = b;
+ * }
+ *
+ * can be written as
+ *
+ * unsigned int lt = constant_time_lt(a, b);
+ * c = a & lt | b & ~lt;
+ */
+
+/*
+ * Returns the given value with the MSB copied to all the other
+ * bits. Uses the fact that arithmetic shift shifts-in the sign bit.
+ * However, this is not ensured by the C standard so you may need to
+ * replace this with something else on odd CPUs.
+ */
+static inline unsigned int constant_time_msb(unsigned int a);
+
+/*
+ * Returns 0xff..f if a < b and 0 otherwise.
+ */
+inline unsigned int constant_time_lt(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b);
+
+/*
+ * Returns 0xff..f if a >= b and 0 otherwise.
+ */
+inline unsigned int constant_time_ge(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b);
+
+/*
+ * Returns 0xff..f if a == 0 and 0 otherwise.
+ */
+inline unsigned int constant_time_is_zero(unsigned int a);
+/* Convenience method for getting an 8-bit mask. */
+inline unsigned char constant_time_is_zero_8(unsigned int a);
+
+
+/*
+ * Returns 0xff..f if a == b and 0 otherwise.
+ */
+inline unsigned int constant_time_eq(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b);
+
+static inline unsigned int constant_time_msb(unsigned int a)
+       {
+       return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
+       }
+
+inline unsigned int constant_time_lt(unsigned int a, unsigned int b)
+       {
+       unsigned int lt;
+       /* Case 1: msb(a) == msb(b). a < b iff the MSB of a - b is set.*/
+       lt = ~(a ^ b) & (a - b);
+       /* Case 2: msb(a) != msb(b). a < b iff the MSB of b is set. */
+       lt |= ~a & b;
+       return constant_time_msb(lt);
+       }
+
+inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b)
+       {
+       return (unsigned char)(constant_time_lt(a, b));
+       }
+
+inline unsigned int constant_time_ge(unsigned int a, unsigned int b)
+       {
+       unsigned int ge;
+       /* Case 1: msb(a) == msb(b). a >= b iff the MSB of a - b is not set.*/
+       ge = ~((a ^ b) | (a - b));
+       /* Case 2: msb(a) != msb(b). a >= b iff the MSB of a is set. */
+       ge |= a & ~b;
+       return constant_time_msb(ge);
+       }
+
+inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b)
+       {
+       return (unsigned char)(constant_time_ge(a, b));
+       }
+
+inline unsigned int constant_time_is_zero(unsigned int a)
+       {
+       return constant_time_msb(~a & (a - 1));
+       }
+
+inline unsigned char constant_time_is_zero_8(unsigned int a)
+       {
+       return (unsigned char)(constant_time_is_zero(a));
+       }
+
+inline unsigned int constant_time_eq(unsigned int a, unsigned int b)
+       {
+       return constant_time_is_zero(a ^ b);
+       }
+
+inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b)
+       {
+       return (unsigned char)(constant_time_eq(a, b));
+       }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* HEADER_CONSTANT_TIME_LOCL_H */
diff --git a/crypto/constant_time_test.c b/crypto/constant_time_test.c
new file mode 100644 (file)
index 0000000..89fad7d
--- /dev/null
@@ -0,0 +1,205 @@
+/* crypto/constant_time_test.c */
+/*
+ * Utilities for constant-time cryptography.
+ *
+ * Author: Emilia Kasper (emilia@openssl.org)
+ * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
+ * (Google).
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "../crypto/constant_time_locl.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static const unsigned int CONSTTIME_TRUE = ~0;
+static const unsigned int CONSTTIME_FALSE = 0;
+static const unsigned char CONSTTIME_TRUE_8 = ~0;
+static const unsigned char CONSTTIME_FALSE_8 = 0;
+
+static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
+       const char* op_name, unsigned int a, unsigned int b, int is_true)
+       {
+       unsigned c = op(a, b);
+       if (is_true && c != CONSTTIME_TRUE)
+               {
+               fprintf(stderr, "Test failed for %s(%du, %du): expected %du "
+                       "(TRUE), got %du\n", op_name, a, b, CONSTTIME_TRUE, c);
+               return 1;
+               }
+       else if (!is_true && c != CONSTTIME_FALSE)
+               {
+               fprintf(stderr, "Test failed for  %s(%du, %du): expected %du "
+                       "(FALSE), got %du\n", op_name, a, b, CONSTTIME_FALSE,
+                       c);
+               return 1;
+               }
+        return 0;
+       }
+
+static int test_binary_op_8(unsigned char (*op)(unsigned int a, unsigned int b),
+       const char* op_name, unsigned int a, unsigned int b, int is_true)
+       {
+       unsigned char c = op(a, b);
+       if (is_true && c != CONSTTIME_TRUE_8)
+               {
+               fprintf(stderr, "Test failed for %s(%du, %du): expected %u "
+                       "(TRUE), got %u\n", op_name, a, b, CONSTTIME_TRUE_8, c);
+               return 1;
+               }
+       else if (!is_true && c != CONSTTIME_FALSE_8)
+               {
+               fprintf(stderr, "Test failed for  %s(%du, %du): expected %u "
+                       "(FALSE), got %u\n", op_name, a, b, CONSTTIME_FALSE_8,
+                       c);
+               return 1;
+               }
+        return 0;
+       }
+
+static int test_is_zero(unsigned int a)
+       {
+       unsigned int c = constant_time_is_zero(a);
+       if (a == 0 && c != CONSTTIME_TRUE)
+               {
+               fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+                       "expected %du (TRUE), got %du\n", a, CONSTTIME_TRUE, c);
+               return 1;
+               }
+       else if (a != 0 && c != CONSTTIME_FALSE)
+               {
+               fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+                       "expected %du (FALSE), got %du\n", a, CONSTTIME_FALSE,
+                       c);
+               return 1;
+               }
+        return 0;
+       }
+
+static int test_is_zero_8(unsigned int a)
+       {
+       unsigned char c = constant_time_is_zero_8(a);
+       if (a == 0 && c != CONSTTIME_TRUE_8)
+               {
+               fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+                       "expected %u (TRUE), got %u\n", a, CONSTTIME_TRUE_8, c);
+               return 1;
+               }
+       else if (a != 0 && c != CONSTTIME_FALSE)
+               {
+               fprintf(stderr, "Test failed for constant_time_is_zero(%du): "
+                       "expected %u (FALSE), got %u\n", a, CONSTTIME_FALSE_8,
+                       c);
+               return 1;
+               }
+        return 0;
+       }
+
+static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX/2-1,
+                                     UINT_MAX/2, UINT_MAX/2+1, UINT_MAX-1,
+                                     UINT_MAX};
+
+int main(int argc, char *argv[])
+       {
+       unsigned int a, b, i, j;
+       int num_failed = 0, num_all = 0;
+       fprintf(stdout, "Testing constant time operations...\n");
+
+       for (i = 0; i < sizeof(test_values)/sizeof(int); ++i)
+               {
+               a = test_values[i];
+               num_failed += test_is_zero(a);
+               num_failed += test_is_zero_8(a);
+               num_failed += test_binary_op(&constant_time_lt,
+                       "constant_time_lt", a, a, 0);
+               num_failed += test_binary_op_8(&constant_time_lt_8,
+                       "constant_time_lt_8", a, a, 0);
+               num_failed += test_binary_op(&constant_time_ge,
+                       "constant_time_ge", a, a, 1);
+               num_failed += test_binary_op_8(&constant_time_ge_8,
+                       "constant_time_ge_8", a, a, 1);
+               num_failed += test_binary_op(&constant_time_eq,
+                       "constant_time_eq", a, a, 1);
+               num_failed += test_binary_op_8(&constant_time_eq_8,
+                       "constant_time_eq_8", a, a, 1);
+               num_all += 8;
+               for (j = i + 1; j < sizeof(test_values)/sizeof(int); ++j)
+                       {
+                       b = test_values[j];
+                       num_failed += test_binary_op(&constant_time_lt,
+                               "constant_time_lt", a, b, a < b);
+                       num_failed += test_binary_op_8(&constant_time_lt_8,
+                               "constant_time_lt_8", a, b, a < b);
+                       num_failed += test_binary_op(&constant_time_lt,
+                               "constant_time_lt_8", b, a, b < a);
+                       num_failed += test_binary_op_8(&constant_time_lt_8,
+                               "constant_time_lt_8", b, a, b < a);
+                       num_failed += test_binary_op(&constant_time_ge,
+                               "constant_time_ge", a, b, a >= b);
+                       num_failed += test_binary_op_8(&constant_time_ge_8,
+                               "constant_time_ge_8", a, b, a >= b);
+                       num_failed += test_binary_op(&constant_time_ge,
+                               "constant_time_ge", b, a, b >= a);
+                       num_failed += test_binary_op_8(&constant_time_ge_8,
+                               "constant_time_ge_8", b, a, b >= a);
+                       num_failed += test_binary_op(&constant_time_eq,
+                               "constant_time_eq", a, b, a == b);
+                       num_failed += test_binary_op_8(&constant_time_eq_8,
+                               "constant_time_eq_8", a, b, a == b);
+                       num_failed += test_binary_op(&constant_time_eq,
+                               "constant_time_eq", b, a, b == a);
+                       num_failed += test_binary_op_8(&constant_time_eq_8,
+                               "constant_time_eq_8", b, a, b == a);
+                       num_all += 12;
+                       }
+               }
+
+       if (!num_failed)
+               {
+               fprintf(stdout, "ok (ran %d tests)\n", num_all);
+               return EXIT_SUCCESS;
+               }
+       else
+               {
+               fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
+               return EXIT_FAILURE;
+               }
+       }
index aa1f1bdec2cde42fc28ded1a9e34d0dd83a4ff0d..c018b643f22b25c8113600ff8f8ad44355aad085 100644 (file)
@@ -547,26 +547,27 @@ s3_both.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
 s3_both.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
 s3_both.o: ../include/openssl/tls1.h ../include/openssl/x509.h
 s3_both.o: ../include/openssl/x509_vfy.h s3_both.c ssl_locl.h
-s3_cbc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
-s3_cbc.o: ../include/openssl/buffer.h ../include/openssl/comp.h
-s3_cbc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
-s3_cbc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
-s3_cbc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
-s3_cbc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
-s3_cbc.o: ../include/openssl/evp.h ../include/openssl/hmac.h
-s3_cbc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
-s3_cbc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
-s3_cbc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
-s3_cbc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
-s3_cbc.o: ../include/openssl/pem.h ../include/openssl/pem2.h
-s3_cbc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
-s3_cbc.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
-s3_cbc.o: ../include/openssl/sha.h ../include/openssl/srtp.h
-s3_cbc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
-s3_cbc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
-s3_cbc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
-s3_cbc.o: ../include/openssl/tls1.h ../include/openssl/x509.h
-s3_cbc.o: ../include/openssl/x509_vfy.h s3_cbc.c ssl_locl.h
+s3_cbc.o: ../crypto/constant_time_locl.h ../e_os.h ../include/openssl/asn1.h
+s3_cbc.o: ../include/openssl/bio.h ../include/openssl/buffer.h
+s3_cbc.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+s3_cbc.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
+s3_cbc.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+s3_cbc.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+s3_cbc.o: ../include/openssl/err.h ../include/openssl/evp.h
+s3_cbc.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+s3_cbc.o: ../include/openssl/lhash.h ../include/openssl/md5.h
+s3_cbc.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
+s3_cbc.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+s3_cbc.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
+s3_cbc.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+s3_cbc.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h
+s3_cbc.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s3_cbc.o: ../include/openssl/srtp.h ../include/openssl/ssl.h
+s3_cbc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s3_cbc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s3_cbc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s3_cbc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s3_cbc.c
+s3_cbc.o: ssl_locl.h
 s3_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
 s3_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 s3_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h
index 1a07e1511fa8b44832bfda2f8b6ec5ba207770b7..d7ae3cf7359c2038d8af06ef2d1a83c4f5eb2c6c 100644 (file)
@@ -53,6 +53,7 @@
  *
  */
 
+#include "../crypto/constant_time_locl.h"
 #include "ssl_locl.h"
 
 #include <openssl/md5.h>
  * supported by TLS.) */
 #define MAX_HASH_BLOCK_SIZE 128
 
-/* Some utility functions are needed:
- *
- * These macros return the given value with the MSB copied to all the other
- * bits. They use the fact that arithmetic shift shifts-in the sign bit.
- * However, this is not ensured by the C standard so you may need to replace
- * them with something else on odd CPUs. */
-#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) )
-#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))
-
-/* constant_time_lt returns 0xff if a<b and 0x00 otherwise. */
-static unsigned constant_time_lt(unsigned a, unsigned b)
-       {
-       a -= b;
-       return DUPLICATE_MSB_TO_ALL(a);
-       }
-
-/* constant_time_ge returns 0xff if a>=b and 0x00 otherwise. */
-static unsigned constant_time_ge(unsigned a, unsigned b)
-       {
-       a -= b;
-       return DUPLICATE_MSB_TO_ALL(~a);
-       }
-
-/* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */
-static unsigned char constant_time_eq_8(unsigned a, unsigned b)
-       {
-       unsigned c = a ^ b;
-       c--;
-       return DUPLICATE_MSB_TO_ALL_8(c);
-       }
-
 /* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
  * record in |rec| by updating |rec->length| in constant time.
  *
@@ -127,7 +97,7 @@ int ssl3_cbc_remove_padding(const SSL* s,
        rec->length -= padding_length;
        rec->type |= padding_length<<8; /* kludge: pass padding length */
        return (int)((good & 1) | (~good & -1));
-}
+       }
 
 /* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
  * record in |rec| in constant time and returns 1 if the padding is valid and
@@ -208,7 +178,7 @@ int tls1_cbc_remove_padding(const SSL* s,
 
        for (i = 0; i < to_check; i++)
                {
-               unsigned char mask = constant_time_ge(padding_length, i);
+               unsigned char mask = constant_time_ge_8(padding_length, i);
                unsigned char b = rec->data[rec->length-1-i];
                /* The final |padding_length+1| bytes should all have the value
                 * |padding_length|. Therefore the XOR should be zero. */
@@ -216,15 +186,9 @@ int tls1_cbc_remove_padding(const SSL* s,
                }
 
        /* If any of the final |padding_length+1| bytes had the wrong value,
-        * one or more of the lower eight bits of |good| will be cleared. We
-        * AND the bottom 8 bits together and duplicate the result to all the
-        * bits. */
-       good &= good >> 4;
-       good &= good >> 2;
-       good &= good >> 1;
-       good <<= sizeof(good)*8-1;
-       good = DUPLICATE_MSB_TO_ALL(good);
-
+        * one or more of the lower eight bits of |good| will be cleared.
+        */
+       good = constant_time_eq(0xff, good & 0xff);
        padding_length = good & (padding_length+1);
        rec->length -= padding_length;
        rec->type |= padding_length<<8; /* kludge: pass padding length */
@@ -296,8 +260,8 @@ void ssl3_cbc_copy_mac(unsigned char* out,
        memset(rotated_mac, 0, md_size);
        for (i = scan_start, j = 0; i < orig_len; i++)
                {
-               unsigned char mac_started = constant_time_ge(i, mac_start);
-               unsigned char mac_ended = constant_time_ge(i, mac_end);
+               unsigned char mac_started = constant_time_ge_8(i, mac_start);
+               unsigned char mac_ended = constant_time_ge_8(i, mac_end);
                unsigned char b = rec->data[i];
                rotated_mac[j++] |= b & mac_started & ~mac_ended;
                j &= constant_time_lt(j,md_size);
@@ -683,8 +647,8 @@ void ssl3_cbc_digest_record(
                                b = data[k-header_length];
                        k++;
 
-                       is_past_c = is_block_a & constant_time_ge(j, c);
-                       is_past_cp1 = is_block_a & constant_time_ge(j, c+1);
+                       is_past_c = is_block_a & constant_time_ge_8(j, c);
+                       is_past_cp1 = is_block_a & constant_time_ge_8(j, c+1);
                        /* If this is the block containing the end of the
                         * application data, and we are at the offset for the
                         * 0x80 value, then overwrite b with 0x80. */
index 9963a39645826e796d2eaf8958d563ca164f66d1..bc4a9200aff8fcc2581c684b053a4a3020316ecb 100644 (file)
@@ -66,6 +66,7 @@ SRPTEST=      srptest
 V3NAMETEST=    v3nametest
 ASN1TEST=      asn1test
 HEARTBEATTEST=  heartbeat_test
+CONSTTIMETEST=  constant_time_test
 
 TESTS=         alltests
 
@@ -77,7 +78,8 @@ EXE=  $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT)  $(ECDSATEST)$(EXE_EXT) $(ECDHTEST)
        $(RANDTEST)$(EXE_EXT) $(DHTEST)$(EXE_EXT) $(ENGINETEST)$(EXE_EXT) \
        $(BFTEST)$(EXE_EXT) $(CASTTEST)$(EXE_EXT) $(SSLTEST)$(EXE_EXT) $(EXPTEST)$(EXE_EXT) $(DSATEST)$(EXE_EXT) $(RSATEST)$(EXE_EXT) \
        $(EVPTEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) $(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) \
-       $(ASN1TEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT)
+       $(ASN1TEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT) \
+       $(CONSTTIMETEST)$(EXE_EXT)
 
 # $(METHTEST)$(EXE_EXT)
 
@@ -90,7 +92,7 @@ OBJ=  $(BNTEST).o $(ECTEST).o  $(ECDSATEST).o $(ECDHTEST).o $(IDEATEST).o \
        $(RANDTEST).o $(DHTEST).o $(ENGINETEST).o $(CASTTEST).o \
        $(BFTEST).o  $(SSLTEST).o  $(DSATEST).o  $(EXPTEST).o $(RSATEST).o \
        $(EVPTEST).o $(IGETEST).o $(JPAKETEST).o $(ASN1TEST).o $(V3NAMETEST).o \
-       $(HEARTBEATTEST).o
+       $(HEARTBEATTEST).o $(CONSTTIMETEST).o
 
 SRC=   $(BNTEST).c $(ECTEST).c  $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
        $(MD2TEST).c  $(MD4TEST).c $(MD5TEST).c \
@@ -100,7 +102,7 @@ SRC=        $(BNTEST).c $(ECTEST).c  $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
        $(RANDTEST).c $(DHTEST).c $(ENGINETEST).c $(CASTTEST).c \
        $(BFTEST).c  $(SSLTEST).c $(DSATEST).c   $(EXPTEST).c $(RSATEST).c \
        $(EVPTEST).c $(IGETEST).c $(JPAKETEST).c $(SRPTEST).c $(ASN1TEST).c \
-       $(V3NAMETEST).c $(HEARTBEATTEST).c
+       $(V3NAMETEST).c $(HEARTBEATTEST).c $(CONSTTIMETEST).c
 
 EXHEADER= 
 HEADER=        testutil.h $(EXHEADER)
@@ -143,7 +145,8 @@ alltests: \
        test_enc test_x509 test_rsa test_crl test_sid \
        test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
        test_ss test_ca test_engine test_evp test_ssl test_tsa test_ige \
-       test_jpake test_srp test_cms test_ocsp test_v3name test_heartbeat
+       test_jpake test_srp test_cms test_ocsp test_v3name test_heartbeat \
+       test_constant_time
 
 test_evp: $(EVPTEST)$(EXE_EXT) evptests.txt
        ../util/shlib_wrap.sh ./$(EVPTEST) evptests.txt
@@ -337,6 +340,10 @@ test_v3name: $(V3NAMETEST)$(EXE_EXT)
 test_heartbeat: $(HEARTBEATTEST)$(EXE_EXT)
        ../util/shlib_wrap.sh ./$(HEARTBEATTEST)
 
+test_constant_time: $(CONSTTIMETEST)$(EXE_EXT)
+       @echo "Test constant time utilites"
+       ../util/shlib_wrap.sh ./$(CONSTTIMETEST)
+
 lint:
        lint -DLINT $(INCLUDES) $(SRC)>fluff
 
@@ -501,6 +508,9 @@ $(V3NAMETEST)$(EXE_EXT): $(V3NAMETEST).o $(DLIBCRYPTO)
 $(HEARTBEATTEST)$(EXE_EXT): $(HEARTBEATTEST).o $(DLIBCRYPTO)
        @target=$(HEARTBEATTEST); $(BUILD_CMD_STATIC)
 
+$(CONSTTIMETEST)$(EXE_EXT): $(CONSTTIMETEST).o
+       @target=$(CONSTTIMETEST) $(BUILD_CMD)
+
 #$(AESTEST).o: $(AESTEST).c
 #      $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c
 
@@ -546,6 +556,9 @@ bntest.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
 bntest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h bntest.c
 casttest.o: ../e_os.h ../include/openssl/cast.h ../include/openssl/e_os2.h
 casttest.o: ../include/openssl/opensslconf.h casttest.c
+constant_time_test.o: ../crypto/constant_time_locl.h ../e_os.h
+constant_time_test.o: ../include/openssl/e_os2.h
+constant_time_test.o: ../include/openssl/opensslconf.h constant_time_test.c
 destest.o: ../include/openssl/des.h ../include/openssl/des_old.h
 destest.o: ../include/openssl/e_os2.h ../include/openssl/opensslconf.h
 destest.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h