int main(int argc, char **argv)
{
    uint8_t u8; uint16_t u16; uint32_t u32;
    
    uint32_t stuffer_size = nondet_uint32();
	__CPROVER_assume(stuffer_size > 0);
	
	uint32_t entropy_size = nondet_uint32();
	__CPROVER_assume(entropy_size > 0);
	
	uint8_t entropy[entropy_size];
    struct s2n_stuffer stuffer;
	
    GUARD(s2n_stuffer_alloc(&stuffer, stuffer_size));

    struct s2n_blob in = {.data = entropy,.size = entropy_size};
    GUARD(s2n_stuffer_write(&stuffer, &in));

	GUARD(s2n_stuffer_wipe(&stuffer));
	while(nondet_bool()) {
        GUARD(s2n_stuffer_write_uint8(&stuffer, nondet_uint64()));
    }

    while(nondet_bool()) {
        GUARD(s2n_stuffer_read_uint8(&stuffer, &u8));
    }

    GUARD(s2n_stuffer_wipe(&stuffer));
    while(nondet_bool()) {
        GUARD(s2n_stuffer_write_uint16(&stuffer, nondet_uint64()));
    }

    while(nondet_bool()) {
        GUARD(s2n_stuffer_read_uint16(&stuffer, &u16));
    }

    GUARD(s2n_stuffer_wipe(&stuffer));
    while(nondet_bool()) {
        GUARD(s2n_stuffer_write_uint24(&stuffer, nondet_uint64()));
    }

    while(nondet_bool()) {
        GUARD(s2n_stuffer_read_uint24(&stuffer, &u32));
    }

    GUARD(s2n_stuffer_wipe(&stuffer));
    while(nondet_bool()) {
        GUARD(s2n_stuffer_write_uint32(&stuffer, nondet_uint64()));
    }

    while(nondet_bool()) {
        GUARD(s2n_stuffer_read_uint32(&stuffer, &u32));
    }

    GUARD(s2n_stuffer_free(&stuffer));
}
Beispiel #2
0
int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length)
{
    if (s2n_stuffer_data_available(&conn->handshake.io) < TLS_HANDSHAKE_HEADER_LENGTH) {
        S2N_ERROR(S2N_ERR_SIZE_MISMATCH);
    }

    /* read the message header */
    GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, message_type));
    GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, length));

    return 0;
}
Beispiel #3
0
int s2n_server_status_recv(struct s2n_connection *conn)
{
    uint8_t type;
    struct s2n_blob status = { .data = NULL, .size = 0 };

    GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type));
    GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &status.size));
    status.data = s2n_stuffer_raw_read(&conn->handshake.io, status.size);
    notnull_check(status.data);

    if (type == S2N_STATUS_REQUEST_OCSP) {
        GUARD(s2n_alloc(&conn->status_response, status.size));
        memcpy_check(conn->status_response.data, status.data, status.size);
        conn->status_response.size = status.size;
    }

    return 0;
}
Beispiel #4
0
int s2n_server_cert_recv(struct s2n_connection *conn)
{
    uint32_t size_of_all_certificates;
    GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &size_of_all_certificates));

    S2N_ERROR_IF(size_of_all_certificates > s2n_stuffer_data_available(&conn->handshake.io) || size_of_all_certificates < 3, S2N_ERR_BAD_MESSAGE);

    s2n_cert_public_key public_key;
    GUARD(s2n_pkey_zero_init(&public_key));

    s2n_cert_type cert_type;
    struct s2n_blob cert_chain = {0};
    cert_chain.data = s2n_stuffer_raw_read(&conn->handshake.io, size_of_all_certificates);
    cert_chain.size = size_of_all_certificates;

    S2N_ERROR_IF(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data,
                                                        cert_chain.size, &cert_type, &public_key) != S2N_CERT_OK, S2N_ERR_CERT_UNTRUSTED);

    s2n_authentication_method expected_auth_method = conn->secure.cipher_suite->auth_method;

    switch (cert_type) {
    case S2N_CERT_TYPE_RSA_SIGN:
        if (expected_auth_method == S2N_AUTHENTICATION_RSA) {
            break;
        }
    case S2N_CERT_TYPE_ECDSA_SIGN:
        if (expected_auth_method == S2N_AUTHENTICATION_ECDSA) {
            break;
        }
    default:
        S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED);
    }
    
    conn->secure.client_cert_type = cert_type;
    s2n_pkey_setup_for_type(&public_key, cert_type);
    conn->secure.server_public_key = public_key;
    return 0;
}
int s2n_server_status_recv(struct s2n_connection *conn)
{
    uint8_t type;
    struct s2n_blob status = { .data = NULL, .size = 0 };

    GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type));
    GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &status.size));
    status.data = s2n_stuffer_raw_read(&conn->handshake.io, status.size);
    notnull_check(status.data);

    if (type == S2N_STATUS_REQUEST_OCSP) {
        GUARD(s2n_alloc(&conn->status_response, status.size));
        memcpy_check(conn->status_response.data, status.data, status.size);
        conn->status_response.size = status.size;
    }

    conn->handshake.next_state = SERVER_HELLO_DONE;

    if (conn->pending.cipher_suite->key_exchange_alg->flags & S2N_KEY_EXCHANGE_EPH) {
        conn->handshake.next_state = SERVER_KEY;
    }

    return 0;
}
s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
                                                                uint8_t *cert_chain_in, uint32_t cert_chain_len,
                                                                s2n_cert_type *cert_type, struct s2n_pkey *public_key_out) {

    if (!validator->skip_cert_validation && !s2n_x509_trust_store_has_certs(validator->trust_store)) {
        return S2N_CERT_ERR_UNTRUSTED;
    }

    DEFER_CLEANUP(X509_STORE_CTX *ctx = NULL, X509_STORE_CTX_free_pointer);

    struct s2n_blob cert_chain_blob = {.data = cert_chain_in, .size = cert_chain_len};
    DEFER_CLEANUP(struct s2n_stuffer cert_chain_in_stuffer = {{0}}, s2n_stuffer_free);
    if (s2n_stuffer_init(&cert_chain_in_stuffer, &cert_chain_blob) < 0) {
        return S2N_CERT_ERR_INVALID;
    }
    if (s2n_stuffer_write(&cert_chain_in_stuffer, &cert_chain_blob) < 0) {
        return S2N_CERT_ERR_INVALID;
    }

    uint32_t certificate_count = 0;

    X509 *server_cert = NULL;

    DEFER_CLEANUP(struct s2n_pkey public_key = {{{0}}}, s2n_pkey_free);
    s2n_pkey_zero_init(&public_key);

    while (s2n_stuffer_data_available(&cert_chain_in_stuffer) && certificate_count < validator->max_chain_depth) {
        uint32_t certificate_size = 0;

        if (s2n_stuffer_read_uint24(&cert_chain_in_stuffer, &certificate_size) < 0) {
            return S2N_CERT_ERR_INVALID;
        }

        if (certificate_size == 0 || certificate_size > s2n_stuffer_data_available(&cert_chain_in_stuffer)) {
            return S2N_CERT_ERR_INVALID;
        }

        struct s2n_blob asn1cert = {0};
        asn1cert.data = s2n_stuffer_raw_read(&cert_chain_in_stuffer, certificate_size);
        asn1cert.size = certificate_size;
        if (asn1cert.data == NULL) {
            return S2N_CERT_ERR_INVALID;
        }

        const uint8_t *data = asn1cert.data;

        if (!validator->skip_cert_validation) {
            /* the cert is der encoded, just convert it. */
            server_cert = d2i_X509(NULL, &data, asn1cert.size);
            if (!server_cert) {
                return S2N_CERT_ERR_INVALID;
            }

            /* add the cert to the chain. */
            if (!sk_X509_push(validator->cert_chain, server_cert)) {
                X509_free(server_cert);
                return S2N_CERT_ERR_INVALID;
            }
         }

        /* Pull the public key from the first certificate */
        if (certificate_count == 0) {
            if (s2n_asn1der_to_public_key_and_type(&public_key, cert_type, &asn1cert) < 0) {
                return S2N_CERT_ERR_INVALID;
            }
        }

        certificate_count++;
    }

    /* if this occurred we exceeded validator->max_chain_depth */
    if (!validator->skip_cert_validation && s2n_stuffer_data_available(&cert_chain_in_stuffer)) {
        return S2N_CERT_ERR_MAX_CHAIN_DEPTH_EXCEEDED;
    }

    if (certificate_count < 1) {
        return S2N_CERT_ERR_INVALID;
    }


    if (!validator->skip_cert_validation) {
        X509 *leaf = sk_X509_value(validator->cert_chain, 0);
        if (!leaf) {
            return S2N_CERT_ERR_INVALID;
        }

        if (conn->verify_host_fn && !s2n_verify_host_information(validator, conn, leaf)) {
            return S2N_CERT_ERR_UNTRUSTED;
        }

        /* now that we have a chain, get the store and check against it. */
        ctx = X509_STORE_CTX_new();

        int op_code = X509_STORE_CTX_init(ctx, validator->trust_store->trust_store, leaf,
                                          validator->cert_chain);

        if (op_code <= 0) {
            return S2N_CERT_ERR_INVALID;
        }

        X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx);
        X509_VERIFY_PARAM_set_depth(param, validator->max_chain_depth);


        uint64_t current_sys_time = 0;
        conn->config->wall_clock(conn->config->sys_clock_ctx, &current_sys_time);

        /* this wants seconds not nanoseconds */
        time_t current_time = (time_t)(current_sys_time / 1000000000);
        X509_STORE_CTX_set_time(ctx, 0, current_time);

        op_code = X509_verify_cert(ctx);

        if (op_code <= 0) {
            return S2N_CERT_ERR_UNTRUSTED;
        }
    }


    *public_key_out = public_key;

    /* Reset the old struct, so we don't clean up public_key_out */
    s2n_pkey_zero_init(&public_key);

    return S2N_CERT_OK;
}