⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlsv1_client.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * wpa_supplicant: TLSv1 client (RFC 2246) * Copyright (c) 2006, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "base64.h"#include "md5.h"#include "sha1.h"#include "crypto.h"#include "tls.h"#include "tlsv1_common.h"#include "tlsv1_client.h"#include "x509v3.h"/* TODO: * Support for a message fragmented across several records (RFC 2246, 6.2.1) */struct tlsv1_client {	enum {		CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE,		SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST,		SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC,		SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED,		ESTABLISHED, FAILED	} state;	struct tlsv1_record_layer rl;	u8 session_id[TLS_SESSION_ID_MAX_LEN];	size_t session_id_len;	u8 client_random[TLS_RANDOM_LEN];	u8 server_random[TLS_RANDOM_LEN];	u8 master_secret[TLS_MASTER_SECRET_LEN];	u8 alert_level;	u8 alert_description;	unsigned int certificate_requested:1;	unsigned int session_resumed:1;	unsigned int ticket:1;	unsigned int ticket_key:1;	struct crypto_public_key *server_rsa_key;	struct crypto_hash *verify_md5_client;	struct crypto_hash *verify_sha1_client;	struct crypto_hash *verify_md5_server;	struct crypto_hash *verify_sha1_server;	struct crypto_hash *verify_md5_cert;	struct crypto_hash *verify_sha1_cert;#define MAX_CIPHER_COUNT 30	u16 cipher_suites[MAX_CIPHER_COUNT];	size_t num_cipher_suites;	u16 prev_cipher_suite;	u8 *client_hello_ext;	size_t client_hello_ext_len;	/* The prime modulus used for Diffie-Hellman */	u8 *dh_p;	size_t dh_p_len;	/* The generator used for Diffie-Hellman */	u8 *dh_g;	size_t dh_g_len;	/* The server's Diffie-Hellman public value */	u8 *dh_ys;	size_t dh_ys_len;	struct x509_certificate *trusted_certs;	struct x509_certificate *client_cert;	struct crypto_private_key *client_key;};static int tls_derive_keys(struct tlsv1_client *conn,			   const u8 *pre_master_secret,			   size_t pre_master_secret_len);static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,					   const u8 *in_data, size_t *in_len);static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,					   const u8 *in_data, size_t *in_len);static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,					 const u8 *in_data, size_t *in_len);static void tls_alert(struct tlsv1_client *conn, u8 level, u8 description){	conn->alert_level = level;	conn->alert_description = description;}static void tls_verify_hash_add(struct tlsv1_client *conn, const u8 *buf,				size_t len){	if (conn->verify_md5_client && conn->verify_sha1_client) {		crypto_hash_update(conn->verify_md5_client, buf, len);		crypto_hash_update(conn->verify_sha1_client, buf, len);	}	if (conn->verify_md5_server && conn->verify_sha1_server) {		crypto_hash_update(conn->verify_md5_server, buf, len);		crypto_hash_update(conn->verify_sha1_server, buf, len);	}	if (conn->verify_md5_cert && conn->verify_sha1_cert) {		crypto_hash_update(conn->verify_md5_cert, buf, len);		crypto_hash_update(conn->verify_sha1_cert, buf, len);	}}static u8 * tls_send_alert(struct tlsv1_client *conn,			   u8 level, u8 description,			   size_t *out_len){	u8 *alert, *pos, *length;	wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);	*out_len = 0;	alert = os_malloc(10);	if (alert == NULL)		return NULL;	pos = alert;	/* TLSPlaintext */	/* ContentType type */	*pos++ = TLS_CONTENT_TYPE_ALERT;	/* ProtocolVersion version */	WPA_PUT_BE16(pos, TLS_VERSION);	pos += 2;	/* uint16 length (to be filled) */	length = pos;	pos += 2;	/* opaque fragment[TLSPlaintext.length] */	/* Alert */	/* AlertLevel level */	*pos++ = level;	/* AlertDescription description */	*pos++ = description;	WPA_PUT_BE16(length, pos - length - 2);	*out_len = pos - alert;	return alert;}static u8 * tls_send_client_hello(struct tlsv1_client *conn,				  size_t *out_len){	u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;	struct os_time now;	size_t len, i;	wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello");	*out_len = 0;	os_get_time(&now);	WPA_PUT_BE32(conn->client_random, now.sec);	if (os_get_random(conn->client_random + 4, TLS_RANDOM_LEN - 4)) {		wpa_printf(MSG_ERROR, "TLSv1: Could not generate "			   "client_random");		return NULL;	}	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",		    conn->client_random, TLS_RANDOM_LEN);	len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;	hello = os_malloc(len);	if (hello == NULL)		return NULL;	end = hello + len;	rhdr = hello;	pos = rhdr + TLS_RECORD_HEADER_LEN;	/* opaque fragment[TLSPlaintext.length] */	/* Handshake */	hs_start = pos;	/* HandshakeType msg_type */	*pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO;	/* uint24 length (to be filled) */	hs_length = pos;	pos += 3;	/* body - ClientHello */	/* ProtocolVersion client_version */	WPA_PUT_BE16(pos, TLS_VERSION);	pos += 2;	/* Random random: uint32 gmt_unix_time, opaque random_bytes */	os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN);	pos += TLS_RANDOM_LEN;	/* SessionID session_id */	*pos++ = conn->session_id_len;	os_memcpy(pos, conn->session_id, conn->session_id_len);	pos += conn->session_id_len;	/* CipherSuite cipher_suites<2..2^16-1> */	WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites);	pos += 2;	for (i = 0; i < conn->num_cipher_suites; i++) {		WPA_PUT_BE16(pos, conn->cipher_suites[i]);		pos += 2;	}	/* CompressionMethod compression_methods<1..2^8-1> */	*pos++ = 1;	*pos++ = TLS_COMPRESSION_NULL;	if (conn->client_hello_ext) {		os_memcpy(pos, conn->client_hello_ext,			  conn->client_hello_ext_len);		pos += conn->client_hello_ext_len;	}	WPA_PUT_BE24(hs_length, pos - hs_length - 3);	tls_verify_hash_add(conn, hs_start, pos - hs_start);	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,			      rhdr, end - rhdr, pos - hs_start, out_len) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		os_free(hello);		return NULL;	}	conn->state = SERVER_HELLO;	return hello;}static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,				    const u8 *in_data, size_t *in_len){	const u8 *pos, *end;	size_t left, len, i;	u16 cipher_suite;	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "			   "received content type 0x%x", ct);		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_UNEXPECTED_MESSAGE);		return -1;	}	pos = in_data;	left = *in_len;	if (left < 4)		goto decode_error;	/* HandshakeType msg_type */	if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "			   "message %d (expected ServerHello)", *pos);		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_UNEXPECTED_MESSAGE);		return -1;	}	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");	pos++;	/* uint24 length */	len = WPA_GET_BE24(pos);	pos += 3;	left -= 4;	if (len > left)		goto decode_error;	/* body - ServerHello */	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);	end = pos + len;	/* ProtocolVersion server_version */	if (end - pos < 2)		goto decode_error;	if (WPA_GET_BE16(pos) != TLS_VERSION) {		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "			   "ServerHello");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_PROTOCOL_VERSION);		return -1;	}	pos += 2;	/* Random random */	if (end - pos < TLS_RANDOM_LEN)		goto decode_error;	os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);	pos += TLS_RANDOM_LEN;	wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",		    conn->server_random, TLS_RANDOM_LEN);	/* SessionID session_id */	if (end - pos < 1)		goto decode_error;	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)		goto decode_error;	if (conn->session_id_len && conn->session_id_len == *pos &&	    os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {		pos += 1 + conn->session_id_len;		wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");		conn->session_resumed = 1;	} else {		conn->session_id_len = *pos;		pos++;		os_memcpy(conn->session_id, pos, conn->session_id_len);		pos += conn->session_id_len;	}	wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",		    conn->session_id, conn->session_id_len);	/* CipherSuite cipher_suite */	if (end - pos < 2)		goto decode_error;	cipher_suite = WPA_GET_BE16(pos);	pos += 2;	for (i = 0; i < conn->num_cipher_suites; i++) {		if (cipher_suite == conn->cipher_suites[i])			break;	}	if (i == conn->num_cipher_suites) {		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "			   "cipher suite 0x%04x", cipher_suite);		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_ILLEGAL_PARAMETER);		return -1;	}	if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {		wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "			   "cipher suite for a resumed connection (0x%04x != "			   "0x%04x)", cipher_suite, conn->prev_cipher_suite);		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_ILLEGAL_PARAMETER);		return -1;	}	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "			   "record layer");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	conn->prev_cipher_suite = cipher_suite;	if (conn->session_resumed || conn->ticket_key)		tls_derive_keys(conn, NULL, 0);	/* CompressionMethod compression_method */	if (end - pos < 1)		goto decode_error;	if (*pos != TLS_COMPRESSION_NULL) {		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "			   "compression 0x%02x", *pos);		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_ILLEGAL_PARAMETER);		return -1;	}	pos++;	if (end != pos) {		wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "			    "end of ServerHello", pos, end - pos);		goto decode_error;	}	*in_len = end - in_data;	conn->state = (conn->session_resumed || conn->ticket) ?		SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;	return 0;decode_error:	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);	return -1;}static int tls_server_key_exchange_allowed(struct tlsv1_client *conn){	const struct tls_cipher_suite *suite;	/* RFC 2246, Section 7.4.3 */	suite = tls_get_cipher_suite(conn->rl.cipher_suite);	if (suite == NULL)		return 0;	switch (suite->key_exchange) {	case TLS_KEY_X_DHE_DSS:	case TLS_KEY_X_DHE_DSS_EXPORT:	case TLS_KEY_X_DHE_RSA:	case TLS_KEY_X_DHE_RSA_EXPORT:	case TLS_KEY_X_DH_anon_EXPORT:	case TLS_KEY_X_DH_anon:		return 1;	case TLS_KEY_X_RSA_EXPORT:		return 1 /* FIX: public key len > 512 bits */;	default:		return 0;	}}static int tls_process_certificate(struct tlsv1_client *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);		tls_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);		tls_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);		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);		return -1;	}	if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)		return tls_process_server_key_exchange(conn, ct, in_data,						       in_len);	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)		return tls_process_certificate_request(conn, ct, in_data,						       in_len);	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)		return tls_process_server_hello_done(conn, ct, in_data,						     in_len);	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "			   "message %d (expected Certificate/"			   "ServerKeyExchange/CertificateRequest/"			   "ServerHelloDone)", type);		tls_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;	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -