Esempio n. 1
0
int
tls_process_segment(packet_t *packet, struct tcphdr *tcp)
{
    struct SSLConnection *conn;
    const u_char *payload = packet_payload(packet);
    uint32_t size_payload = packet_payloadlen(packet);
    uint8_t *out;
    uint32_t outl = packet->payload_len;
    out = sng_malloc(outl);
    struct in_addr ip_src, ip_dst;
    uint16_t sport = packet->src.port;
    uint16_t dport = packet->dst.port;

    // Convert addresses
    inet_pton(AF_INET, packet->src.ip, &ip_src);
    inet_pton(AF_INET, packet->dst.ip, &ip_dst);

    // Try to find a session for this ip
    if ((conn = tls_connection_find(ip_src, sport))) {
        // Update last connection direction
        conn->direction = tls_connection_dir(conn, ip_src, sport);

        // Check current connection state
        switch (conn->state) {
            case TCP_STATE_SYN:
                // First SYN received, this package must be SYN/ACK
                if (tcp->th_flags & TH_SYN & ~TH_ACK)
                    conn->state = TCP_STATE_SYN_ACK;
                break;
            case TCP_STATE_SYN_ACK:
                // We expect an ACK packet here
                if (tcp->th_flags & ~TH_SYN & TH_ACK)
                    conn->state = TCP_STATE_ESTABLISHED;
                break;
            case TCP_STATE_ACK:
            case TCP_STATE_ESTABLISHED:
                // Process data segment!
                if (tls_process_record(conn, payload, size_payload, &out, &outl) == 0) {
                    if ((int32_t) outl > 0) {
                        packet_set_payload(packet, out, outl);
                        packet_set_type(packet, PACKET_SIP_TLS);
                        return 0;
                    }
                }
                break;
            case TCP_STATE_FIN:
            case TCP_STATE_CLOSED:
                // We can delete this connection
                tls_connection_destroy(conn);
                break;
        }
    } else {
        if (tcp->th_flags & TH_SYN & ~TH_ACK) {
            // New connection, store it status and leave
            tls_connection_create(ip_src, sport, ip_dst, dport);
        }
    }

    sng_free(out);
    return 0;
}
Esempio n. 2
0
int
tls_process_record_handshake(struct SSLConnection *conn, const opaque *fragment, const int len)
{
    struct Handshake *handshake;
    struct ClientHello *clienthello;
    struct ServerHello *serverhello;
    struct ClientKeyExchange *clientkeyex;
    const opaque *body;

    // Get Handshake data
    handshake = (struct Handshake *) fragment;

    if (UINT24_INT(handshake->length) > 0) {
        // Hanshake body pointer
        body = fragment + sizeof(struct Handshake);

        switch (handshake->type) {
            case hello_request:
                break;
            case client_hello:
                // Store client random
                clienthello = (struct ClientHello *) body;
                memcpy(&conn->client_random, &clienthello->random, sizeof(struct Random));

                // Check we have a TLS handshake
                if (!(clienthello->client_version.major == 0x03)) {
                    tls_connection_destroy(conn);
                    return 1;
                }

                // Only TLS 1.0, 1.1 or 1.2 connections
                if (clienthello->client_version.minor != 0x01
                        && clienthello->client_version.minor != 0x02
                        && clienthello->client_version.minor != 0x03) {
                    tls_connection_destroy(conn);
                    return 1;
                }

                // Store TLS version
                conn->version = clienthello->client_version.minor;
                break;
            case server_hello:
                // Store server random
                serverhello = (struct ServerHello *) body;
                memcpy(&conn->server_random, &serverhello->random, sizeof(struct Random));
                // Get the selected cipher
                memcpy(&conn->cipher_suite,
                       body + sizeof(struct ServerHello) + serverhello->session_id_length,
                       sizeof(uint16_t));
                // Check if we have a handled cipher
                if (tls_connection_load_cipher(conn) != 0) {
                    tls_connection_destroy(conn);
                    return 1;
                }
                break;
            case certificate:
            case certificate_request:
            case server_hello_done:
            case certificate_verify:
                break;
            case client_key_exchange:
                // Decrypt PreMasterKey
                clientkeyex = (struct ClientKeyExchange *) body;

                RSA_private_decrypt(UINT16_INT(clientkeyex->length),
                                    (const unsigned char *) &clientkeyex->exchange_keys,
                                    (unsigned char *) &conn->pre_master_secret,
                                    conn->server_private_key->pkey.rsa, RSA_PKCS1_PADDING);

                tls_debug_print_hex("client_random", &conn->client_random, 32);
                tls_debug_print_hex("server_random", &conn->server_random, 32);

                uint8_t *seed = sng_malloc(sizeof(struct Random) * 2);
                memcpy(seed, &conn->client_random, sizeof(struct Random));
                memcpy(seed + sizeof(struct Random), &conn->server_random, sizeof(struct Random));

                if (conn->version < 3) {
                    // Get MasterSecret
                    PRF((unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                        (unsigned char *) &conn->pre_master_secret, sizeof(struct PreMasterSecret),
                        (unsigned char *) "master secret", seed, sizeof(struct Random) * 2);
                } else {
                    PRF12((unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                          (unsigned char *) &conn->pre_master_secret, sizeof(struct PreMasterSecret),
                          (unsigned char *) "master secret", seed, sizeof(struct Random) * 2);
                }
                tls_debug_print_hex("master_secret", conn->master_secret.random, 48);

                memcpy(seed, &conn->server_random, sizeof(struct Random) * 2);
                memcpy(seed + sizeof(struct Random), &conn->client_random, sizeof(struct Random));

                // Generate MACs, Write Keys and IVs
                if (conn->version < 3) {
                    PRF((unsigned char *) &conn->key_material, sizeof(struct tls_data),
                        (unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                        (unsigned char *) "key expansion", seed, sizeof(struct Random) * 2);
                } else {
                    PRF12((unsigned char *) &conn->key_material, sizeof(struct tls_data),
                          (unsigned char *) &conn->master_secret, sizeof(struct MasterSecret),
                          (unsigned char *) "key expansion", seed, sizeof(struct Random) * 2);
                }

                tls_debug_print_hex("client_write_MAC_key", conn->key_material.client_write_MAC_key, 20);
                tls_debug_print_hex("server_write_MAC_key", conn->key_material.server_write_MAC_key, 20);
                tls_debug_print_hex("client_write_key",     conn->key_material.client_write_key, 32);
                tls_debug_print_hex("server_write_key",     conn->key_material.server_write_key, 32);
                tls_debug_print_hex("client_write_IV",      conn->key_material.client_write_IV, 16);
                tls_debug_print_hex("server_write_IV",      conn->key_material.server_write_IV, 16);

                // Done with the seed
                sng_free(seed);

                // Create Client decoder
                EVP_CIPHER_CTX_init(&conn->client_cipher_ctx);
                EVP_CipherInit(&conn->client_cipher_ctx, conn->ciph,
                               conn->key_material.client_write_key, conn->key_material.client_write_IV,
                               0);

                EVP_CIPHER_CTX_init(&conn->server_cipher_ctx);
                EVP_CipherInit(&conn->server_cipher_ctx, conn->ciph,
                               conn->key_material.server_write_key, conn->key_material.server_write_IV,
                               0);

                break;
            case new_session_ticket:
            case finished:
                break;
            default:
                if (conn->encrypted) {
                    // Encrypted Hanshake Message
                    uint8_t *decoded = sng_malloc(len);
                    uint32_t decodedlen = len;
                    tls_process_record_data(conn, fragment, len, &decoded, &decodedlen);
                    sng_free(decoded);
                }
                break;
        }
    }

    return 0;
}