Exemplo n.º 1
0
int main(int argc, char *argv[])
{
	char *buf;
	size_t len;
	struct x509_certificate *certs = NULL, *last = NULL, *cert;
	int i, reason;

	wpa_debug_level = 0;

	if (argc < 3 || strcmp(argv[1], "-v") != 0) {
		printf("usage: test_x509v3 -v <cert1.der> <cert2.der> ..\n");
		return -1;
	}

	for (i = 2; i < argc; i++) {
		printf("Reading: %s\n", argv[i]);
		buf = os_readfile(argv[i], &len);
		if (buf == NULL) {
			printf("Failed to read '%s'\n", argv[i]);
			return -1;
		}

		cert = x509_certificate_parse((u8 *) buf, len);
		if (cert == NULL) {
			printf("Failed to parse X.509 certificate\n");
			return -1;
		}

		free(buf);

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

	printf("\n\nValidating certificate chain\n");
	if (x509_certificate_chain_validate(last, certs, &reason, 0) < 0) {
		printf("\nCertificate chain validation failed: %d\n", reason);
		return -1;
	}
	printf("\nCertificate chain is valid\n");

	return 0;
}
/**
 * tls_parse_cert - Parse DER encoded X.509 certificate and get public key
 * @buf: ASN.1 DER encoded certificate
 * @len: Length of the buffer
 * @pk: Buffer for returning the allocated public key
 * Returns: 0 on success, -1 on failure
 *
 * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves
 * the public key from it. The caller is responsible for freeing the public key
 * by calling crypto_public_key_free().
 */
int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk)
{
	struct x509_certificate *cert;

	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate",
		    buf, len);

	*pk = crypto_public_key_from_cert(buf, len);
	if (*pk)
		return 0;

	cert = x509_certificate_parse(buf, len);
	if (cert == NULL) {
		wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 "
			   "certificate");
		return -1;
	}

	/* TODO
	 * verify key usage (must allow encryption)
	 *
	 * All certificate profiles, key and cryptographic formats are
	 * defined by the IETF PKIX working group [PKIX]. When a key
	 * usage extension is present, the digitalSignature bit must be
	 * set for the key to be eligible for signing, as described
	 * above, and the keyEncipherment bit must be present to allow
	 * encryption, as described above. The keyAgreement bit must be
	 * set on Diffie-Hellman certificates. (PKIX: RFC 3280)
	 */

	*pk = crypto_public_key_import(cert->public_key, cert->public_key_len);
	x509_certificate_free(cert);

	if (*pk == NULL) {
		wpa_printf(MSG_ERROR, "TLSv1: Failed to import "
			   "server public key");
		return -1;
	}

	return 0;
}
Exemplo n.º 3
0
int main(int argc, char *argv[])
{
	FILE *f;
	u8 buf[3000];
	size_t len;
	struct x509_certificate *cert;

	wpa_debug_level = 0;

	f = fopen(argv[1], "rb");
	if (f == NULL)
		return -1;
	len = fread(buf, 1, sizeof(buf), f);
	fclose(f);

	cert = x509_certificate_parse(buf, len);
	if (cert == NULL)
		printf("Failed to parse X.509 certificate\n");
	x509_certificate_free(cert);

	return 0;
}
Exemplo n.º 4
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;
}