Example #1
0
int s2n_server_key_recv(struct s2n_connection *conn)
{
    struct s2n_hash_state *signature_hash = &conn->secure.signature_hash;
    const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg;
    struct s2n_stuffer *in = &conn->handshake.io;
    struct s2n_blob data_to_verify = {0};

    /* Read the KEX data */
    union s2n_kex_raw_server_data kex_data = {{{0}}};
    GUARD(s2n_kex_server_key_recv_read_data(key_exchange, conn, &data_to_verify, &kex_data));

    /* Add common signature data */
    if (conn->actual_protocol_version == S2N_TLS12) {
        s2n_hash_algorithm hash_algorithm;
        s2n_signature_algorithm signature_algorithm;
        GUARD(s2n_get_signature_hash_pair_if_supported(in, &hash_algorithm, &signature_algorithm));
        GUARD(s2n_hash_init(signature_hash, hash_algorithm));
    } else {
        GUARD(s2n_hash_init(signature_hash, conn->secure.conn_hash_alg));
    }
    GUARD(s2n_hash_update(signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
    GUARD(s2n_hash_update(signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));

    /* Add KEX specific data */
    GUARD(s2n_hash_update(signature_hash, data_to_verify.data, data_to_verify.size));

    /* Verify the signature */
    uint16_t signature_length;
    GUARD(s2n_stuffer_read_uint16(in, &signature_length));

    struct s2n_blob signature = {.size = signature_length, .data = s2n_stuffer_raw_read(in, signature_length)};
    notnull_check(signature.data);
    gt_check(signature_length, 0);

    S2N_ERROR_IF(s2n_pkey_verify(&conn->secure.server_public_key, signature_hash, &signature) < 0, S2N_ERR_BAD_MESSAGE);

    /* We don't need the key any more, so free it */
    GUARD(s2n_pkey_free(&conn->secure.server_public_key));

    /* Parse the KEX data into whatever form needed and save it to the connection object */
    GUARD(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data));

    return 0;
}

int s2n_ecdhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, union s2n_kex_raw_server_data *raw_server_data)
{
    struct s2n_stuffer *in = &conn->handshake.io;

    GUARD(s2n_ecc_read_ecc_params(in, data_to_verify, &raw_server_data->ecdhe_data));
    return 0;
}

int s2n_ecdhe_server_key_recv_parse_data(struct s2n_connection *conn, union s2n_kex_raw_server_data *raw_server_data)
{
    GUARD(s2n_ecc_parse_ecc_params(&conn->secure.server_ecc_params, &raw_server_data->ecdhe_data));
    return 0;
}
Example #2
0
/* A TLS CBC record looks like ..
 *
 * [ Payload data ] [ HMAC ] [ Padding ] [ Padding length byte ]
 *
 * Each byte in the padding is expected to be set to the same value
 * as the padding length byte. So if the padding length byte is '2'
 * then the padding will be [ '2', '2' ] (there'll be three bytes
 * set to that value if you include the padding length byte).
 *
 * The goal of s2n_verify_cbc() is to verify that the padding and hmac
 * are correct, without leaking (via timing) how much padding there
 * actually is: as this is considered secret. 
 *
 * In addition to our efforts here though, s2n also wraps any CBC
 * verification error (or record parsing error in general) with
 * a randomized delay of between 1ms and 10 seconds. See s2n_connection.c.
 * This amount of delay randomization is sufficient to increase the
 * complexity of attack for even a 1 microsecond timing leak (which
 * is quite large) by a factor of around 83 trillion.
 */
int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, struct s2n_blob *decrypted)
{
    struct s2n_hmac_state copy;

    int mac_digest_size = s2n_hmac_digest_size(hmac->alg);

    /* The record has to be at least big enough to contain the MAC,
     * plus the padding length byte */
    gt_check(decrypted->size, mac_digest_size);

    int payload_and_padding_size = decrypted->size - mac_digest_size;

    /* Determine what the padding length is */
    uint8_t padding_length = decrypted->data[decrypted->size - 1];

    int payload_length = MAX(payload_and_padding_size - padding_length - 1, 0);

    /* Update the MAC */
    GUARD(s2n_hmac_update(hmac, decrypted->data, payload_length));
    GUARD(s2n_hmac_copy(&copy, hmac));

    /* Check the MAC */
    uint8_t check_digest[S2N_MAX_DIGEST_LEN];
    lte_check(mac_digest_size, sizeof(check_digest));
    GUARD(s2n_hmac_digest_two_compression_rounds(hmac, check_digest, mac_digest_size));

    int mismatches = s2n_constant_time_equals(decrypted->data + payload_length, check_digest, mac_digest_size) ^ 1;

    /* Compute a MAC on the rest of the data so that we perform the same number of hash operations */
    GUARD(s2n_hmac_update(&copy, decrypted->data + payload_length + mac_digest_size, decrypted->size - payload_length - mac_digest_size - 1));

    /* SSLv3 doesn't specify what the padding should actually be */
    if (conn->actual_protocol_version == S2N_SSLv3) {
        return 0 - mismatches;
    }

    /* Check the maximum amount that could theoritically be padding */
    int check = MIN(255, (payload_and_padding_size - 1));

    int cutoff = check - padding_length;
    for (int i = 0, j = decrypted->size - 1 - check; i < check && j < decrypted->size; i++, j++) {
        uint8_t mask = ~(0xff << ((i >= cutoff) * 8));
        mismatches |= (decrypted->data[j] ^ padding_length) & mask;
    }

    if (mismatches) {
        S2N_ERROR(S2N_ERR_CBC_VERIFY);
    }

    return 0;
}
static int s2n_ecdhe_server_key_recv(struct s2n_connection *conn)
{
    struct s2n_hash_state signature_hash;
    struct s2n_stuffer *in = &conn->handshake.io;
    struct s2n_blob ecdhparams;
    struct s2n_blob signature;
    uint16_t signature_length;

    /* Read server ECDH params and calculate their hash */
    GUARD(s2n_ecc_read_ecc_params(&conn->secure.server_ecc_params, in, &ecdhparams));

    GUARD(s2n_hash_init(&signature_hash, conn->secure.signature_digest_alg));

    if (conn->actual_protocol_version == S2N_TLS12) {
        uint8_t hash_algorithm;
        uint8_t signature_algorithm;

        GUARD(s2n_stuffer_read_uint8(in, &hash_algorithm));
        GUARD(s2n_stuffer_read_uint8(in, &signature_algorithm));

        if (signature_algorithm != TLS_SIGNATURE_ALGORITHM_RSA) {
            S2N_ERROR(S2N_ERR_BAD_MESSAGE);
        }

        switch(hash_algorithm) {
            case TLS_HASH_ALGORITHM_MD5:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_MD5));
                break;
            case TLS_HASH_ALGORITHM_SHA1:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA1));
                break;
            case TLS_HASH_ALGORITHM_SHA224:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA224));
                break;
            case TLS_HASH_ALGORITHM_SHA256:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA256));
                break;
            case TLS_HASH_ALGORITHM_SHA384:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA384));
                break;
            case TLS_HASH_ALGORITHM_SHA512:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA512));
                break;
            default:
                S2N_ERROR(S2N_ERR_BAD_MESSAGE);
        }
    }

    GUARD(s2n_hash_update(&signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
    GUARD(s2n_hash_update(&signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
    GUARD(s2n_hash_update(&signature_hash, ecdhparams.data, ecdhparams.size));

    /* Verify the signature */
    GUARD(s2n_stuffer_read_uint16(in, &signature_length));
    signature.size = signature_length;
    signature.data = s2n_stuffer_raw_read(in, signature.size);
    notnull_check(signature.data);

    gt_check(signature_length, 0);

    if (s2n_rsa_verify(&conn->secure.server_rsa_public_key, &signature_hash, &signature) < 0) {
        S2N_ERROR(S2N_ERR_BAD_MESSAGE);
    }

    /* We don't need the key any more, so free it */
    GUARD(s2n_rsa_public_key_free(&conn->secure.server_rsa_public_key));

    return 0;
}
static int s2n_dhe_server_key_recv(struct s2n_connection *conn)
{
    struct s2n_hash_state signature_hash;
    struct s2n_stuffer *in = &conn->handshake.io;
    struct s2n_blob p, g, Ys, serverDHparams, signature;
    uint16_t p_length;
    uint16_t g_length;
    uint16_t Ys_length;
    uint16_t signature_length;

    /* Keep a copy to the start of the whole structure for the signature check */
    serverDHparams.data = s2n_stuffer_raw_read(in, 0);
    notnull_check(serverDHparams.data);

    /* Read each of the three elements in */
    GUARD(s2n_stuffer_read_uint16(in, &p_length));
    p.size = p_length;
    p.data = s2n_stuffer_raw_read(in, p.size);
    notnull_check(p.data);

    GUARD(s2n_stuffer_read_uint16(in, &g_length));
    g.size = g_length;
    g.data = s2n_stuffer_raw_read(in, g.size);
    notnull_check(g.data);

    GUARD(s2n_stuffer_read_uint16(in, &Ys_length));
    Ys.size = Ys_length;
    Ys.data = s2n_stuffer_raw_read(in, Ys.size);
    notnull_check(Ys.data);

    /* Now we know the total size of the structure */
    serverDHparams.size = 2 + p_length + 2 + g_length + 2 + Ys_length;

    GUARD(s2n_hash_init(&signature_hash, conn->secure.signature_digest_alg));

    if (conn->actual_protocol_version == S2N_TLS12) {
        uint8_t hash_algorithm;
        uint8_t signature_algorithm;

        GUARD(s2n_stuffer_read_uint8(in, &hash_algorithm));
        GUARD(s2n_stuffer_read_uint8(in, &signature_algorithm));

        if (signature_algorithm != TLS_SIGNATURE_ALGORITHM_RSA) {
            S2N_ERROR(S2N_ERR_BAD_MESSAGE);
        }

        switch(hash_algorithm) {
            case TLS_HASH_ALGORITHM_MD5:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_MD5));
                break;
            case TLS_HASH_ALGORITHM_SHA1:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA1));
                break;
            case TLS_HASH_ALGORITHM_SHA224:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA224));
                break;
            case TLS_HASH_ALGORITHM_SHA256:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA256));
                break;
            case TLS_HASH_ALGORITHM_SHA384:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA384));
                break;
            case TLS_HASH_ALGORITHM_SHA512:
                GUARD(s2n_hash_init(&signature_hash, S2N_HASH_SHA512));
                break;
            default:
                S2N_ERROR(S2N_ERR_BAD_MESSAGE);
        }
    }

    GUARD(s2n_hash_update(&signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
    GUARD(s2n_hash_update(&signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
    GUARD(s2n_hash_update(&signature_hash, serverDHparams.data, serverDHparams.size));

    GUARD(s2n_stuffer_read_uint16(in, &signature_length));
    signature.size = signature_length;
    signature.data = s2n_stuffer_raw_read(in, signature.size);
    notnull_check(signature.data);

    gt_check(signature_length, 0);

    if (s2n_rsa_verify(&conn->secure.server_rsa_public_key, &signature_hash, &signature) < 0) {
        S2N_ERROR(S2N_ERR_BAD_MESSAGE);
    }

    /* We don't need the key any more, so free it */
    GUARD(s2n_rsa_public_key_free(&conn->secure.server_rsa_public_key));

    /* Copy the DH details */
    GUARD(s2n_dh_p_g_Ys_to_dh_params(&conn->secure.server_dh_params, &p, &g, &Ys));

    return 0;
}
Example #5
0
int64_t s2n_public_random(int64_t max)
{
    uint64_t r;

    gt_check(max, 0);

    while(1) {
        struct s2n_blob blob = { .data = (void *) &r, sizeof(r) };
        GUARD(s2n_get_public_random_data(&blob));

        /* Imagine an int was one byte and UINT_MAX was 256. If the
         * caller asked for s2n_random(129, ...) we'd end up in
         * trouble. Each number in the range 0...127 would be twice
         * as likely as 128. That's because r == 0 % 129 -> 0, and
         * r == 129 % 129 -> 0, but only r == 128 returns 128,
         * r == 257 is out of range.
         *
         * To de-bias the dice, we discard values of r that are higher
         * that the highest multiple of 'max' an int can support. If
         * max is a uint, then in the worst case we discard 50% - 1 r's.
         * But since 'max' is an int and INT_MAX is <= UINT_MAX / 2,
         * in the worst case we discard 25% - 1 r's.
         */
        if (r < (UINT64_MAX - (UINT64_MAX % max))) {
            return r % max;
        }
    }

    return -1;
}

#ifndef OPENSSL_IS_BORINGSSL

int s2n_openssl_compat_rand(unsigned char *buf, int num)
{
    struct s2n_blob out = {.data = buf, .size = num};

    if(s2n_get_private_random_data(&out) < 0) {
        return 0;
    }
    return 1;
}

int s2n_openssl_compat_status(void)
{
    return 1;
}

int s2n_openssl_compat_init(ENGINE *unused)
{
    return 1;
}

RAND_METHOD s2n_openssl_rand_method = {
    .seed = NULL,
    .bytes = s2n_openssl_compat_rand,
    .cleanup = NULL,
    .add = NULL,
    .pseudorand = s2n_openssl_compat_rand,
    .status = s2n_openssl_compat_status
};
#endif

int s2n_init(void)
{
    GUARD(s2n_mem_init());

    OPEN:
    entropy_fd = open(ENTROPY_SOURCE, O_RDONLY);
    if (entropy_fd == -1) {
        if (errno == EINTR) {
            goto OPEN;
        }
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

#if defined(MAP_INHERIT_ZERO)
    if ((zero_if_forked_ptr = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE,
                                   MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

    if (minherit(zero_if_forked_ptr, sizeof(int), MAP_INHERIT_ZERO) == -1) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }
#else

    if (pthread_atfork(NULL, NULL, s2n_on_fork) != 0) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }
#endif

    GUARD(s2n_check_fork());

#ifndef OPENSSL_IS_BORINGSSL
    /* Create an engine */
    ENGINE *e = ENGINE_new();
    if (e == NULL ||
        ENGINE_set_id(e, "s2n") != 1 ||
        ENGINE_set_name(e, "s2n entropy generator") != 1 ||
        ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) != 1 ||
        ENGINE_set_init_function(e, s2n_openssl_compat_init) != 1 ||
        ENGINE_set_RAND(e, &s2n_openssl_rand_method) != 1 ||
        ENGINE_add(e) != 1 ||
        ENGINE_free(e) != 1) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

    /* Use that engine for rand() */
    e = ENGINE_by_id("s2n");
    if (e == NULL ||
        ENGINE_init(e) != 1 ||
        ENGINE_set_default(e, ENGINE_METHOD_RAND) != 1) {
        S2N_ERROR(S2N_ERR_OPEN_RANDOM);
    }

#endif

    return 0;
}