Esempio n. 1
0
/**
 * tlsv1_client_deinit - Deinitialize TLSv1 client connection
 * @conn: TLSv1 client connection data from tlsv1_client_init()
 */
void tlsv1_client_deinit(struct tlsv1_client *conn)
{
	crypto_public_key_free(conn->server_rsa_key);
	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
	tlsv1_record_change_write_cipher(&conn->rl);
	tlsv1_record_change_read_cipher(&conn->rl);
	tls_verify_hash_free(&conn->verify);
	os_free(conn->client_hello_ext);
	tlsv1_client_free_dh(conn);
	tlsv1_cred_free(conn->cred);
	os_free(conn);
}
static void tlsv1_server_clear_data(struct tlsv1_server *conn)
{
	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
	tlsv1_record_change_write_cipher(&conn->rl);
	tlsv1_record_change_read_cipher(&conn->rl);
	tls_verify_hash_free(&conn->verify);

	crypto_public_key_free(conn->client_rsa_key);
	conn->client_rsa_key = NULL;

	os_free(conn->session_ticket);
	conn->session_ticket = NULL;
	conn->session_ticket_len = 0;
	conn->use_session_ticket = 0;

	os_free(conn->dh_secret);
	conn->dh_secret = NULL;
	conn->dh_secret_len = 0;
}
Esempio n. 3
0
/**
 * tlsv1_client_shutdown - Shutdown TLS connection
 * @conn: TLSv1 client connection data from tlsv1_client_init()
 * Returns: 0 on success, -1 on failure
 */
int tlsv1_client_shutdown(struct tlsv1_client *conn)
{
	conn->state = CLIENT_HELLO;

	if (tls_verify_hash_init(&conn->verify) < 0) {
		wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
			   "hash");
		return -1;
	}

	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
	tlsv1_record_change_write_cipher(&conn->rl);
	tlsv1_record_change_read_cipher(&conn->rl);

	conn->certificate_requested = 0;
	crypto_public_key_free(conn->server_rsa_key);
	conn->server_rsa_key = NULL;
	conn->session_resumed = 0;

	return 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;
}
static int cavp_rsa_sig_ver(const char *fname)
{
    FILE *f;
    int ret = 0;
    char buf[15000], *pos, *pos2;
    u8 msg[200], n[512], s[512], em[512], e[512];
    size_t msg_len = 0, n_len = 0, s_len = 0, em_len, e_len = 0;
    size_t tmp_len;
    char sha_alg[20];
    int ok = 0;

    printf("CAVP RSA SigVer test vectors from %s\n", fname);

    f = fopen(fname, "r");
    if (f == NULL) {
        printf("%s does not exist - cannot validate CAVP RSA SigVer test vectors\n",
               fname);
        return 0;
    }

    while (fgets(buf, sizeof(buf), f)) {
        pos = os_strchr(buf, '=');
        if (pos == NULL)
            continue;
        pos2 = pos - 1;
        while (pos2 >= buf && *pos2 == ' ')
            *pos2-- = '\0';
        *pos++ = '\0';
        while (*pos == ' ')
            *pos++ = '\0';
        pos2 = os_strchr(pos, '\r');
        if (!pos2)
            pos2 = os_strchr(pos, '\n');
        if (pos2)
            *pos2 = '\0';
        else
            pos2 = pos + os_strlen(pos);

        if (os_strcmp(buf, "SHAAlg") == 0) {
            os_strlcpy(sha_alg, pos, sizeof(sha_alg));
        } else if (os_strcmp(buf, "Msg") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(msg) * 2) {
                printf("Too long Msg\n");
                return -1;
            }
            msg_len = tmp_len / 2;
            if (hexstr2bin(pos, msg, msg_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "n") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(n) * 2) {
                printf("Too long n\n");
                return -1;
            }
            n_len = tmp_len / 2;
            if (hexstr2bin(pos, n, n_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "e") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(e) * 2) {
                printf("Too long e\n");
                return -1;
            }
            e_len = tmp_len / 2;
            if (hexstr2bin(pos, e, e_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "S") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(s) * 2) {
                printf("Too long S\n");
                return -1;
            }
            s_len = tmp_len / 2;
            if (hexstr2bin(pos, s, s_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strncmp(buf, "EM", 2) == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(em) * 2)
                return -1;
            em_len = tmp_len / 2;
            if (hexstr2bin(pos, em, em_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "Result") == 0) {
            const u8 *addr[1];
            size_t len[1];
            struct crypto_public_key *pk;
            int res;
            u8 hash[32];
            size_t hash_len;
            const struct asn1_oid *alg;

            addr[0] = msg;
            len[0] = msg_len;
            if (os_strcmp(sha_alg, "SHA1") == 0) {
                if (sha1_vector(1, addr, len, hash) < 0)
                    return -1;
                hash_len = 20;
                alg = &asn1_sha1_oid;
            } else if (os_strcmp(sha_alg, "SHA256") == 0) {
                if (sha256_vector(1, addr, len, hash) < 0)
                    return -1;
                hash_len = 32;
                alg = &asn1_sha256_oid;
            } else {
                continue;
            }

            printf("\nExpected result: %s\n", pos);
            wpa_hexdump(MSG_INFO, "Hash(Msg)", hash, hash_len);

            pk = crypto_public_key_import_parts(n, n_len,
                                                e, e_len);
            if (pk == NULL) {
                printf("Failed to import public key\n");
                ret++;
                continue;
            }

            res = pkcs1_v15_sig_ver(pk, s, s_len, alg,
                                    hash, hash_len);
            crypto_public_key_free(pk);
            if ((*pos == 'F' && !res) || (*pos != 'F' && res)) {
                printf("FAIL\n");
                ret++;
                continue;
            }

            printf("PASS\n");
            ok++;
        }
    }

    fclose(f);

    if (ret)
        printf("Test case failed\n");
    else
        printf("%d test vectors OK\n", ok);

    return ret;
}