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

📄 tlsv1_client.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	conn->verify_sha1_cert = NULL;	if (alg == SIGN_ALG_RSA)		hlen += MD5_MAC_LEN;	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);	/*	 * RFC 2246, 4.7:	 * In digital signing, one-way hash functions are used as input for a	 * signing algorithm. A digitally-signed element is encoded as an	 * opaque vector <0..2^16-1>, where the length is specified by the	 * signing algorithm and key.	 *	 * In RSA signing, a 36-byte structure of two hashes (one SHA and one	 * MD5) is signed (encrypted with the private key). It is encoded with	 * PKCS #1 block type 0 or type 1 as described in [PKCS1].	 */	signed_start = pos; /* length to be filled */	pos += 2;	clen = end - pos;	if (crypto_private_key_sign_pkcs1(conn->client_key, hash, hlen,					  pos, &clen) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	WPA_PUT_BE16(signed_start, clen);	pos += clen;	WPA_PUT_BE24(hs_length, pos - hs_length - 3);	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,			      rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	pos = rhdr + rlen;	tls_verify_hash_add(conn, hs_start, pos - hs_start);	*msgpos = pos;	return 0;}static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn,					       u8 **msgpos, u8 *end){	u8 *pos, *rhdr;	size_t rlen;	pos = *msgpos;	wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");	rhdr = pos;	pos += TLS_RECORD_HEADER_LEN;	*pos = TLS_CHANGE_CIPHER_SPEC;	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,			      rhdr, end - rhdr, 1, &rlen) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "			   "record layer");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	*msgpos = rhdr + rlen;	return 0;}static int tls_write_client_finished(struct tlsv1_client *conn,				     u8 **msgpos, u8 *end){	u8 *pos, *rhdr, *hs_start, *hs_length;	size_t rlen, hlen;	u8 verify_data[TLS_VERIFY_DATA_LEN];	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];	pos = *msgpos;	wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");	/* Encrypted Handshake Message: Finished */	hlen = MD5_MAC_LEN;	if (conn->verify_md5_client == NULL ||	    crypto_hash_finish(conn->verify_md5_client, hash, &hlen) < 0) {		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		conn->verify_md5_client = NULL;		crypto_hash_finish(conn->verify_sha1_client, NULL, NULL);		conn->verify_sha1_client = NULL;		return -1;	}	conn->verify_md5_client = NULL;	hlen = SHA1_MAC_LEN;	if (conn->verify_sha1_client == NULL ||	    crypto_hash_finish(conn->verify_sha1_client, hash + MD5_MAC_LEN,			       &hlen) < 0) {		conn->verify_sha1_client = NULL;		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	conn->verify_sha1_client = NULL;	if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,		    "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,		    verify_data, TLS_VERIFY_DATA_LEN)) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",			verify_data, TLS_VERIFY_DATA_LEN);	rhdr = pos;	pos += TLS_RECORD_HEADER_LEN;	/* Handshake */	hs_start = pos;	/* HandshakeType msg_type */	*pos++ = TLS_HANDSHAKE_TYPE_FINISHED;	/* uint24 length (to be filled) */	hs_length = pos;	pos += 3;	os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN);	pos += TLS_VERIFY_DATA_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, &rlen) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	pos = rhdr + rlen;	*msgpos = pos;	return 0;}static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn){	size_t len = 0;	struct x509_certificate *cert;	cert = conn->client_cert;	while (cert) {		len += 3 + cert->cert_len;		if (x509_certificate_self_signed(cert))			break;		cert = x509_certificate_get_subject(conn->trusted_certs,						    &cert->issuer);	}	return len;}static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn,					 size_t *out_len){	u8 *msg, *end, *pos;	size_t msglen;	*out_len = 0;	msglen = 1000;	if (conn->certificate_requested)		msglen += tls_client_cert_chain_der_len(conn);	msg = os_malloc(msglen);	if (msg == NULL)		return NULL;	pos = msg;	end = msg + msglen;	if (conn->certificate_requested) {		if (tls_write_client_certificate(conn, &pos, end) < 0) {			os_free(msg);			return NULL;		}	}	if (tls_write_client_key_exchange(conn, &pos, end) < 0 ||	    (conn->certificate_requested && conn->client_key &&	     tls_write_client_certificate_verify(conn, &pos, end) < 0) ||	    tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||	    tls_write_client_finished(conn, &pos, end) < 0) {		os_free(msg);		return NULL;	}	*out_len = pos - msg;	conn->state = SERVER_CHANGE_CIPHER_SPEC;	return msg;}static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn,					size_t *out_len){	u8 *msg, *end, *pos;	*out_len = 0;	msg = os_malloc(1000);	if (msg == NULL)		return NULL;	pos = msg;	end = msg + 1000;	if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||	    tls_write_client_finished(conn, &pos, end) < 0) {		os_free(msg);		return NULL;	}	*out_len = pos - msg;	wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed "		   "successfully");	conn->state = ESTABLISHED;	return msg;}static int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,					  const u8 *buf, size_t *len){	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {		size_t hr_len = WPA_GET_BE24(buf + 1);		if (hr_len > *len - 4) {			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,				  TLS_ALERT_DECODE_ERROR);			return -1;		}		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");		*len = 4 + hr_len;		return 0;	}	switch (conn->state) {	case SERVER_HELLO:		if (tls_process_server_hello(conn, ct, buf, len))			return -1;		break;	case SERVER_CERTIFICATE:		if (tls_process_certificate(conn, ct, buf, len))			return -1;		break;	case SERVER_KEY_EXCHANGE:		if (tls_process_server_key_exchange(conn, ct, buf, len))			return -1;		break;	case SERVER_CERTIFICATE_REQUEST:		if (tls_process_certificate_request(conn, ct, buf, len))			return -1;		break;	case SERVER_HELLO_DONE:		if (tls_process_server_hello_done(conn, ct, buf, len))			return -1;		break;	case SERVER_CHANGE_CIPHER_SPEC:		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))			return -1;		break;	case SERVER_FINISHED:		if (tls_process_server_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, buf, *len);	return 0;}/** * tlsv1_client_handshake - Process TLS handshake * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Input data from TLS peer * @in_len: Input data length * @out_len: Length of the output buffer. * Returns: Pointer to output data, %NULL on failure */u8 * tlsv1_client_handshake(struct tlsv1_client *conn,			    const u8 *in_data, size_t in_len,			    size_t *out_len){	const u8 *pos, *end;	u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct;	size_t in_msg_len;	if (conn->state == CLIENT_HELLO) {		if (in_len)			return NULL;		return tls_send_client_hello(conn, out_len);	}	if (in_data == NULL || in_len == 0)		return NULL;	pos = in_data;	end = in_data + in_len;	in_msg = os_malloc(in_len);	if (in_msg == NULL)		return NULL;	/* Each received packet may include multiple records */	while (pos < end) {		in_msg_len = in_len;		if (tlsv1_record_receive(&conn->rl, pos, end - pos,					 in_msg, &in_msg_len, &alert)) {			wpa_printf(MSG_DEBUG, "TLSv1: Processing received "				   "record failed");			tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);			goto failed;		}		ct = pos[0];		in_pos = in_msg;		in_end = in_msg + in_msg_len;		/* Each received record may include multiple messages of the		 * same ContentType. */		while (in_pos < in_end) {			in_msg_len = in_end - in_pos;			if (tlsv1_client_process_handshake(conn, ct, in_pos,							   &in_msg_len) < 0)				goto failed;			in_pos += in_msg_len;		}		pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);	}	os_free(in_msg);	in_msg = NULL;	switch (conn->state) {	case CLIENT_KEY_EXCHANGE:		msg = tls_send_client_key_exchange(conn, out_len);		break;	case CHANGE_CIPHER_SPEC:		msg = tls_send_change_cipher_spec(conn, out_len);		break;	case ACK_FINISHED:		wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed "			   "successfully");		conn->state = ESTABLISHED;		/* Need to return something to get final TLS ACK. */		msg = os_malloc(1);		*out_len = 0;		break;	default:		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "			   "generating reply", conn->state);		break;	}failed:	os_free(in_msg);	if (conn->alert_level) {		conn->state = FAILED;		os_free(msg);		msg = tls_send_alert(conn, conn->alert_level,				     conn->alert_description, out_len);	}	return msg;}/** * tlsv1_client_encrypt - Encrypt data into TLS tunnel * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to plaintext data to be encrypted * @in_len: Input buffer length * @out_data: Pointer to output buffer (encrypted TLS data) * @out_len: Maximum out_data length  * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. */int tlsv1_client_encrypt(struct tlsv1_client *conn,			 const u8 *in_data, size_t in_len,			 u8 *out_data, size_t out_len){	size_t rlen;	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",			in_data, in_len);	os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len);	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,			      out_data, out_len, in_len, &rlen) < 0) {		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,			  TLS_ALERT_INTERNAL_ERROR);		return -1;	}	return rlen;}/** * tlsv1_client_decrypt - Decrypt data from TLS tunnel * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */int tlsv1_client_decrypt(struct tlsv1_client *conn,			 const u8 *in_data, size_t in_len,			 u8 *out_data, size_t out_len){	const u8 *in_end, *pos;	int res;	u8 alert, *out_end, *out_pos;	size_t olen;	pos = in_data;	in_end = in_data + in_len;	out_pos = out_data;	out_end = out_data + out_len;	while (pos < in_end) {		if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) {			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "				   "0x%x", pos[0]);			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,				  TLS_ALERT_UNEXPECTED_MESSAGE);			return -1;		}		olen = out_end - out_pos;		res = tlsv1_record_receive(&conn->rl, pos, in_end - pos,					   out_pos, &olen, &alert);		if (res < 0) {			wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "				   "failed");			tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);			return -1;		}		out_pos += olen;		if (out_pos > out_end) {			wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough "				   "for processing the received record");			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,				  TLS_ALERT_INTERNAL_ERROR);			return -1;

⌨️ 快捷键说明

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