Commit 2688e7a0 authored by Matt Caswell's avatar Matt Caswell
Browse files

Provide some constant time functions for dealing with size_t values



Also implement the using of them

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
parent 708e06c5
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#ifndef HEADER_CONSTANT_TIME_LOCL_H
# define HEADER_CONSTANT_TIME_LOCL_H

# include <stdlib.h>
# include <openssl/e_os2.h>              /* For 'ossl_inline' */

#ifdef __cplusplus
@@ -102,12 +103,22 @@ static ossl_inline unsigned int constant_time_msb(unsigned int a)
    return 0 - (a >> (sizeof(a) * 8 - 1));
}

static ossl_inline size_t constant_time_msb_s(size_t a)
{
    return 0 - (a >> (sizeof(a) * 8 - 1));
}

static ossl_inline unsigned int constant_time_lt(unsigned int a,
                                                 unsigned int b)
{
    return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
}

static ossl_inline size_t constant_time_lt_s(size_t a, size_t b)
{
    return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
}

static ossl_inline unsigned char constant_time_lt_8(unsigned int a,
                                                    unsigned int b)
{
@@ -120,17 +131,32 @@ static ossl_inline unsigned int constant_time_ge(unsigned int a,
    return ~constant_time_lt(a, b);
}

static ossl_inline size_t constant_time_ge_s(size_t a, size_t b)
{
    return ~constant_time_lt_s(a, b);
}

static ossl_inline unsigned char constant_time_ge_8(unsigned int a,
                                                    unsigned int b)
{
    return (unsigned char)(constant_time_ge(a, b));
}

static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b)
{
    return (unsigned char)(constant_time_ge_s(a, b));
}

static ossl_inline unsigned int constant_time_is_zero(unsigned int a)
{
    return constant_time_msb(~a & (a - 1));
}

static ossl_inline size_t constant_time_is_zero_s(size_t a)
{
    return constant_time_msb_s(~a & (a - 1));
}

static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a)
{
    return (unsigned char)(constant_time_is_zero(a));
@@ -142,12 +168,22 @@ static ossl_inline unsigned int constant_time_eq(unsigned int a,
    return constant_time_is_zero(a ^ b);
}

static ossl_inline size_t constant_time_eq_s(size_t a, size_t b)
{
    return constant_time_is_zero_s(a ^ b);
}

static ossl_inline unsigned char constant_time_eq_8(unsigned int a,
                                                    unsigned int b)
{
    return (unsigned char)(constant_time_eq(a, b));
}

static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b)
{
    return (unsigned char)(constant_time_eq_s(a, b));
}

static ossl_inline unsigned int constant_time_eq_int(int a, int b)
{
    return constant_time_eq((unsigned)(a), (unsigned)(b));
@@ -165,6 +201,13 @@ static ossl_inline unsigned int constant_time_select(unsigned int mask,
    return (mask & a) | (~mask & b);
}

static ossl_inline size_t constant_time_select_s(size_t mask,
                                                 size_t a,
                                                 size_t b)
{
    return (mask & a) | (~mask & b);
}

static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
                                                        unsigned char a,
                                                        unsigned char b)
@@ -178,6 +221,12 @@ static ossl_inline int constant_time_select_int(unsigned int mask, int a,
    return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
}

static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
{
    return (int)(constant_time_select((unsigned)mask, (unsigned)(a),
                                      (unsigned)(b)));
}

#ifdef __cplusplus
}
#endif
+19 −19
Original line number Diff line number Diff line
@@ -1112,7 +1112,7 @@ int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
                            size_t block_size, size_t mac_size)
{
    size_t padding_length;
    unsigned good;
    size_t good;
    const size_t overhead = 1 /* padding length byte */  + mac_size;

    /*
@@ -1122,11 +1122,11 @@ int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
        return 0;

    padding_length = rec->data[rec->length - 1];
    good = constant_time_ge(rec->length, padding_length + overhead);
    good = constant_time_ge_s(rec->length, padding_length + overhead);
    /* SSLv3 requires that the padding is minimal. */
    good &= constant_time_ge(block_size, padding_length + 1);
    good &= constant_time_ge_s(block_size, padding_length + 1);
    rec->length -= good & (padding_length + 1);
    return constant_time_select_int(good, 1, -1);
    return constant_time_select_int_s(good, 1, -1);
}

/*-
@@ -1146,7 +1146,7 @@ int tls1_cbc_remove_padding(const SSL *s,
                            SSL3_RECORD *rec,
                            size_t block_size, size_t mac_size)
{
    unsigned good;
    size_t good;
    size_t padding_length, to_check, i;
    const size_t overhead = 1 /* padding length byte */  + mac_size;
    /* Check if version requires explicit IV */
@@ -1174,7 +1174,7 @@ int tls1_cbc_remove_padding(const SSL *s,
        return 1;
    }

    good = constant_time_ge(rec->length, overhead + padding_length);
    good = constant_time_ge_s(rec->length, overhead + padding_length);
    /*
     * The padding consists of a length byte at the end of the record and
     * then that many bytes of padding, all with the same value as the length
@@ -1189,7 +1189,7 @@ int tls1_cbc_remove_padding(const SSL *s,
        to_check = rec->length;

    for (i = 0; i < to_check; i++) {
        unsigned char mask = constant_time_ge_8(padding_length, i);
        unsigned char mask = constant_time_ge_8_s(padding_length, i);
        unsigned char b = rec->data[rec->length - 1 - i];
        /*
         * The final |padding_length+1| bytes should all have the value
@@ -1202,10 +1202,10 @@ 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.
     */
    good = constant_time_eq(0xff, good & 0xff);
    good = constant_time_eq_s(0xff, good & 0xff);
    rec->length -= good & (padding_length + 1);

    return constant_time_select_int(good, 1, -1);
    return constant_time_select_int_s(good, 1, -1);
}

/*-
@@ -1248,9 +1248,9 @@ void ssl3_cbc_copy_mac(unsigned char *out,
     * MAC's position can only vary by 255 bytes.
     */
    size_t scan_start = 0;
    unsigned i, j;
    unsigned div_spoiler;
    unsigned rotate_offset;
    size_t i, j;
    size_t div_spoiler;
    size_t rotate_offset;

    OPENSSL_assert(rec->orig_len >= md_size);
    OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
@@ -1276,11 +1276,11 @@ void ssl3_cbc_copy_mac(unsigned char *out,

    memset(rotated_mac, 0, md_size);
    for (i = scan_start, j = 0; i < rec->orig_len; i++) {
        unsigned char mac_started = constant_time_ge_8(i, mac_start);
        unsigned char mac_ended = constant_time_ge_8(i, mac_end);
        unsigned char mac_started = constant_time_ge_8_s(i, mac_start);
        unsigned char mac_ended = constant_time_ge_8_s(i, mac_end);
        unsigned char b = rec->data[i];
        rotated_mac[j++] |= b & mac_started & ~mac_ended;
        j &= constant_time_lt(j, md_size);
        j &= constant_time_lt_s(j, md_size);
    }

    /* Now rotate the MAC */
@@ -1290,17 +1290,17 @@ void ssl3_cbc_copy_mac(unsigned char *out,
        /* in case cache-line is 32 bytes, touch second line */
        ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
        out[j++] = rotated_mac[rotate_offset++];
        rotate_offset &= constant_time_lt(rotate_offset, md_size);
        rotate_offset &= constant_time_lt_s(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);
    rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
    for (i = 0; i < md_size; i++) {
        for (j = 0; j < md_size; j++)
            out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
            out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
        rotate_offset++;
        rotate_offset &= constant_time_lt(rotate_offset, md_size);
        rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
    }
#endif
}
+4 −4
Original line number Diff line number Diff line
@@ -400,8 +400,8 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
    for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks;
         i++) {
        unsigned char block[MAX_HASH_BLOCK_SIZE];
        unsigned char is_block_a = constant_time_eq_8(i, index_a);
        unsigned char is_block_b = constant_time_eq_8(i, index_b);
        unsigned char is_block_a = constant_time_eq_8_s(i, index_a);
        unsigned char is_block_b = constant_time_eq_8_s(i, index_b);
        for (j = 0; j < md_block_size; j++) {
            unsigned char b = 0, is_past_c, is_past_cp1;
            if (k < header_length)
@@ -410,8 +410,8 @@ int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
                b = data[k - header_length];
            k++;

            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);
            is_past_c = is_block_a & constant_time_ge_8_s(j, c);
            is_past_cp1 = is_block_a & constant_time_ge_8_s(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