s3_cbc.c: get rid of expensive divisions [from master].
authorAndy Polyakov <appro@openssl.org>
Fri, 8 Feb 2013 15:59:26 +0000 (16:59 +0100)
committerAndy Polyakov <appro@openssl.org>
Fri, 8 Feb 2013 16:01:55 +0000 (17:01 +0100)
(cherry picked from commit e9baceab5a385e570706ca98dec768b2d89d1ac6)

ssl/s3_cbc.c

index 8dfc11e713204fe82014e810e431daf2c7c465c5..d5d00f539be20a4bffa9b8db18a409a54b78aa24 100644 (file)
 #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)
        {
@@ -84,7 +91,7 @@ static unsigned constant_time_ge(unsigned a, unsigned b)
        }
 
 /* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */
-static unsigned char constant_time_eq_8(unsigned char a, unsigned char b)
+static unsigned char constant_time_eq_8(unsigned a, unsigned b)
        {
        unsigned c = a ^ b;
        c--;
@@ -281,16 +288,13 @@ void ssl3_cbc_copy_mac(unsigned char* out,
        rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
 
        memset(rotated_mac, 0, md_size);
-       for (i = scan_start; i < orig_len;)
+       for (i = scan_start, j = 0; i < orig_len; i++)
                {
-               for (j = 0; j < md_size && i < orig_len; i++, j++)
-                       {
-                       unsigned char mac_started = constant_time_ge(i, mac_start);
-                       unsigned char mac_ended = constant_time_ge(i, mac_end);
-                       unsigned char b = 0;
-                       b = rec->data[i];
-                       rotated_mac[j] |= b & mac_started & ~mac_ended;
-                       }
+               unsigned char mac_started = constant_time_ge(i, mac_start);
+               unsigned char mac_ended = constant_time_ge(i, mac_end);
+               unsigned char b = rec->data[i];
+               rotated_mac[j++] |= b & mac_started & ~mac_ended;
+               j &= constant_time_lt(j,md_size);
                }
 
        /* Now rotate the MAC */
@@ -298,16 +302,19 @@ void ssl3_cbc_copy_mac(unsigned char* out,
        j = 0;
        for (i = 0; i < md_size; i++)
                {
-               unsigned char offset = (div_spoiler + rotate_offset + i) % md_size;
-               out[j++] = rotated_mac[offset];
+               out[j++] = rotated_mac[rotate_offset++];
+               rotate_offset &= constant_time_lt(rotate_offset,md_size);
                }
 #else
        memset(out, 0, md_size);
+       rotate_offset = md_size - rotate_offset;
+       rotate_offset &= constant_time_lt(rotate_offset,md_size);
        for (i = 0; i < md_size; i++)
                {
-               unsigned char offset = (div_spoiler + md_size - rotate_offset + i) % md_size;
                for (j = 0; j < md_size; j++)
-                       out[j] |= rotated_mac[i] & constant_time_eq_8(j, offset);
+                       out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
+               rotate_offset++;
+               rotate_offset &= constant_time_lt(rotate_offset,md_size);
                }
 #endif
        }