Пример #1
0
int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct,
				   const u8 *buf, size_t *len)
{
	if (ct == TLS_CONTENT_TYPE_ALERT) {
		if (*len < 2) {
			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
					   TLS_ALERT_DECODE_ERROR);
			return -1;
		}
		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
			   buf[0], buf[1]);
		*len = 2;
		conn->state = FAILED;
		return -1;
	}

	switch (conn->state) {
	case CLIENT_HELLO:
		if (tls_process_client_hello(conn, ct, buf, len))
			return -1;
		break;
	case CLIENT_CERTIFICATE:
		if (tls_process_certificate(conn, ct, buf, len))
			return -1;
		break;
	case CLIENT_KEY_EXCHANGE:
		if (tls_process_client_key_exchange(conn, ct, buf, len))
			return -1;
		break;
	case CERTIFICATE_VERIFY:
		if (tls_process_certificate_verify(conn, ct, buf, len))
			return -1;
		break;
	case CHANGE_CIPHER_SPEC:
		if (tls_process_change_cipher_spec(conn, ct, buf, len))
			return -1;
		break;
	case CLIENT_FINISHED:
		if (tls_process_client_finished(conn, ct, buf, len))
			return -1;
		break;
	default:
		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
			   "while processing received message",
			   conn->state);
		return -1;
	}

	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
		tls_verify_hash_add(&conn->verify, buf, *len);

	return 0;
}
Пример #2
0
static int tls_process_certificate(struct tlsv1_server *conn, u8 ct,
        const u8 *in_data, size_t *in_len) {
    const u8 *pos, *end;
    size_t left, len, list_len, cert_len, idx;
    u8 type;
    struct x509_certificate *chain = NULL, *last = NULL, *cert;
    int reason;

    if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
        wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
                "received content type 0x%x", ct);
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                TLS_ALERT_UNEXPECTED_MESSAGE);
        return -1;
    }

    pos = in_data;
    left = *in_len;

    if (left < 4) {
        wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
                "(len=%lu)", (unsigned long) left);
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                TLS_ALERT_DECODE_ERROR);
        return -1;
    }

    type = *pos++;
    len = WPA_GET_BE24(pos);
    pos += 3;
    left -= 4;

    if (len > left) {
        wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
                "length (len=%lu != left=%lu)",
                (unsigned long) len, (unsigned long) left);
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                TLS_ALERT_DECODE_ERROR);
        return -1;
    }

    if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
        if (conn->verify_peer) {
            wpa_printf(MSG_DEBUG, "TLSv1: Client did not include "
                    "Certificate");
            tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                    TLS_ALERT_UNEXPECTED_MESSAGE);
            return -1;
        }

        return tls_process_client_key_exchange(conn, ct, in_data,
                in_len);
    }
    if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
        wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
                "message %d (expected Certificate/"
                "ClientKeyExchange)", type);
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                TLS_ALERT_UNEXPECTED_MESSAGE);
        return -1;
    }

    wpa_printf(MSG_DEBUG,
            "TLSv1: Received Certificate (certificate_list len %lu)",
            (unsigned long) len);

    /*
     * opaque ASN.1Cert<2^24-1>;
     *
     * struct {
     *     ASN.1Cert certificate_list<1..2^24-1>;
     * } Certificate;
     */

    end = pos + len;

    if (end - pos < 3) {
        wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
                "(left=%lu)", (unsigned long) left);
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                TLS_ALERT_DECODE_ERROR);
        return -1;
    }

    list_len = WPA_GET_BE24(pos);
    pos += 3;

    if ((size_t) (end - pos) != list_len) {
        wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
                "length (len=%lu left=%lu)",
                (unsigned long) list_len,
                (unsigned long) (end - pos));
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                TLS_ALERT_DECODE_ERROR);
        return -1;
    }

    idx = 0;
    while (pos < end) {
        if (end - pos < 3) {
            wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
                    "certificate_list");
            tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                    TLS_ALERT_DECODE_ERROR);
            x509_certificate_chain_free(chain);
            return -1;
        }

        cert_len = WPA_GET_BE24(pos);
        pos += 3;

        if ((size_t) (end - pos) < cert_len) {
            wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
                    "length (len=%lu left=%lu)",
                    (unsigned long) cert_len,
                    (unsigned long) (end - pos));
            tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                    TLS_ALERT_DECODE_ERROR);
            x509_certificate_chain_free(chain);
            return -1;
        }

        wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
                (unsigned long) idx, (unsigned long) cert_len);

        if (idx == 0) {
            crypto_public_key_free(conn->client_rsa_key);
            if (tls_parse_cert(pos, cert_len,
                    &conn->client_rsa_key)) {
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
                        "the certificate");
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                        TLS_ALERT_BAD_CERTIFICATE);
                x509_certificate_chain_free(chain);
                return -1;
            }
        }

        cert = x509_certificate_parse(pos, cert_len);
        if (cert == NULL) {
            wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
                    "the certificate");
            tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
                    TLS_ALERT_BAD_CERTIFICATE);
            x509_certificate_chain_free(chain);
            return -1;
        }

        if (last == NULL)
            chain = cert;
        else
            last->next = cert;
        last = cert;

        idx++;
        pos += cert_len;
    }

    if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
            &reason) < 0) {
        int tls_reason;
        wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
                "validation failed (reason=%d)", reason);
        switch (reason) {
            case X509_VALIDATE_BAD_CERTIFICATE:
                tls_reason = TLS_ALERT_BAD_CERTIFICATE;
                break;
            case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
                tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
                break;
            case X509_VALIDATE_CERTIFICATE_REVOKED:
                tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
                break;
            case X509_VALIDATE_CERTIFICATE_EXPIRED:
                tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
                break;
            case X509_VALIDATE_CERTIFICATE_UNKNOWN:
                tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
                break;
            case X509_VALIDATE_UNKNOWN_CA:
                tls_reason = TLS_ALERT_UNKNOWN_CA;
                break;
            default:
                tls_reason = TLS_ALERT_BAD_CERTIFICATE;
                break;
        }
        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
        x509_certificate_chain_free(chain);
        return -1;
    }

    x509_certificate_chain_free(chain);

    *in_len = end - in_data;

    conn->state = CLIENT_KEY_EXCHANGE;

    return 0;
}