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

📄 tls_openssl.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * WPA Supplicant / SSL/TLS interface functions for openssl * Copyright (c) 2004-2007, 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"#ifndef CONFIG_SMARTCARD#ifndef OPENSSL_NO_ENGINE#define OPENSSL_NO_ENGINE#endif#endif#include <openssl/ssl.h>#include <openssl/err.h>#include <openssl/pkcs12.h>#include <openssl/x509v3.h>#ifndef OPENSSL_NO_ENGINE#include <openssl/engine.h>#endif /* OPENSSL_NO_ENGINE */#include "common.h"#include "tls.h"#if OPENSSL_VERSION_NUMBER >= 0x0090800fL#define OPENSSL_d2i_TYPE const unsigned char **#else#define OPENSSL_d2i_TYPE unsigned char **#endifstatic int tls_openssl_ref_count = 0;struct tls_connection {	SSL *ssl;	BIO *ssl_in, *ssl_out;#ifndef OPENSSL_NO_ENGINE	ENGINE *engine;        /* functional reference to the engine */	EVP_PKEY *private_key; /* the private key if using engine */#endif /* OPENSSL_NO_ENGINE */	char *subject_match, *altsubject_match;	int read_alerts, write_alerts, failed;	tls_session_ticket_cb session_ticket_cb;	void *session_ticket_cb_ctx;	/* SessionTicket received from OpenSSL hello_extension_cb (server) */	u8 *session_ticket;	size_t session_ticket_len;};#ifdef CONFIG_NO_STDOUT_DEBUGstatic void _tls_show_errors(void){	unsigned long err;	while ((err = ERR_get_error())) {		/* Just ignore the errors, since stdout is disabled */	}}#define tls_show_errors(l, f, t) _tls_show_errors()#else /* CONFIG_NO_STDOUT_DEBUG */static void tls_show_errors(int level, const char *func, const char *txt){	unsigned long err;	wpa_printf(level, "OpenSSL: %s - %s %s",		   func, txt, ERR_error_string(ERR_get_error(), NULL));	while ((err = ERR_get_error())) {		wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",			   ERR_error_string(err, NULL));	}}#endif /* CONFIG_NO_STDOUT_DEBUG */#ifdef CONFIG_NATIVE_WINDOWS/* Windows CryptoAPI and access to certificate stores */#include <wincrypt.h>#ifdef __MINGW32_VERSION/* * MinGW does not yet include all the needed definitions for CryptoAPI, so * define here whatever extra is needed. */#define CALG_SSL3_SHAMD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5)#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)#define CERT_STORE_READONLY_FLAG 0x00008000#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000#define CRYPT_ACQUIRE_COMPARE_KEY_FLAG 0x00000004static BOOL WINAPI(*CryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT pCert, DWORD dwFlags,				     void *pvReserved, HCRYPTPROV *phCryptProv,				     DWORD *pdwKeySpec, BOOL *pfCallerFreeProv)= NULL; /* to be loaded from crypt32.dll */static PCCERT_CONTEXT WINAPI(*CertEnumCertificatesInStore)(HCERTSTORE hCertStore,			       PCCERT_CONTEXT pPrevCertContext)= NULL; /* to be loaded from crypt32.dll */static int mingw_load_crypto_func(void){	HINSTANCE dll;	/* MinGW does not yet have full CryptoAPI support, so load the needed	 * function here. */	if (CryptAcquireCertificatePrivateKey)		return 0;	dll = LoadLibrary("crypt32");	if (dll == NULL) {		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 "			   "library");		return -1;	}	CryptAcquireCertificatePrivateKey = GetProcAddress(		dll, "CryptAcquireCertificatePrivateKey");	if (CryptAcquireCertificatePrivateKey == NULL) {		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "			   "CryptAcquireCertificatePrivateKey() address from "			   "crypt32 library");		return -1;	}	CertEnumCertificatesInStore = (void *) GetProcAddress(		dll, "CertEnumCertificatesInStore");	if (CertEnumCertificatesInStore == NULL) {		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "			   "CertEnumCertificatesInStore() address from "			   "crypt32 library");		return -1;	}	return 0;}#else /* __MINGW32_VERSION */static int mingw_load_crypto_func(void){	return 0;}#endif /* __MINGW32_VERSION */struct cryptoapi_rsa_data {	const CERT_CONTEXT *cert;	HCRYPTPROV crypt_prov;	DWORD key_spec;	BOOL free_crypt_prov;};static void cryptoapi_error(const char *msg){	wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",		   msg, (unsigned int) GetLastError());}static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,				 unsigned char *to, RSA *rsa, int padding){	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);	return 0;}static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,				 unsigned char *to, RSA *rsa, int padding){	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);	return 0;}static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,				  unsigned char *to, RSA *rsa, int padding){	struct cryptoapi_rsa_data *priv =		(struct cryptoapi_rsa_data *) rsa->meth->app_data;	HCRYPTHASH hash;	DWORD hash_size, len, i;	unsigned char *buf = NULL;	int ret = 0;	if (priv == NULL) {		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,		       ERR_R_PASSED_NULL_PARAMETER);		return 0;	}	if (padding != RSA_PKCS1_PADDING) {		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,		       RSA_R_UNKNOWN_PADDING_TYPE);		return 0;	}	if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {		wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",			   __func__);		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,		       RSA_R_INVALID_MESSAGE_LENGTH);		return 0;	}	if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))	{		cryptoapi_error("CryptCreateHash failed");		return 0;	}	len = sizeof(hash_size);	if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,			       0)) {		cryptoapi_error("CryptGetHashParam failed");		goto err;	}	if ((int) hash_size != flen) {		wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",			   (unsigned) hash_size, flen);		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,		       RSA_R_INVALID_MESSAGE_LENGTH);		goto err;	}	if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {		cryptoapi_error("CryptSetHashParam failed");		goto err;	}	len = RSA_size(rsa);	buf = os_malloc(len);	if (buf == NULL) {		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);		goto err;	}	if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {		cryptoapi_error("CryptSignHash failed");		goto err;	}	for (i = 0; i < len; i++)		to[i] = buf[len - i - 1];	ret = len;err:	os_free(buf);	CryptDestroyHash(hash);	return ret;}static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,				  unsigned char *to, RSA *rsa, int padding){	wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);	return 0;}static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv){	if (priv == NULL)		return;	if (priv->crypt_prov && priv->free_crypt_prov)		CryptReleaseContext(priv->crypt_prov, 0);	if (priv->cert)		CertFreeCertificateContext(priv->cert);	os_free(priv);}static int cryptoapi_finish(RSA *rsa){	cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);	os_free((void *) rsa->meth);	rsa->meth = NULL;	return 1;}static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store){	HCERTSTORE cs;	const CERT_CONTEXT *ret = NULL;	cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,			   store | CERT_STORE_OPEN_EXISTING_FLAG |			   CERT_STORE_READONLY_FLAG, L"MY");	if (cs == NULL) {		cryptoapi_error("Failed to open 'My system store'");		return NULL;	}	if (strncmp(name, "cert://", 7) == 0) {		unsigned short wbuf[255];		MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);		ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |						 PKCS_7_ASN_ENCODING,						 0, CERT_FIND_SUBJECT_STR,						 wbuf, NULL);	} else if (strncmp(name, "hash://", 7) == 0) {		CRYPT_HASH_BLOB blob;		int len;		const char *hash = name + 7;		unsigned char *buf;		len = os_strlen(hash) / 2;		buf = os_malloc(len);		if (buf && hexstr2bin(hash, buf, len) == 0) {			blob.cbData = len;			blob.pbData = buf;			ret = CertFindCertificateInStore(cs,							 X509_ASN_ENCODING |							 PKCS_7_ASN_ENCODING,							 0, CERT_FIND_HASH,							 &blob, NULL);		}		os_free(buf);	}	CertCloseStore(cs, 0);	return ret;}static int tls_cryptoapi_cert(SSL *ssl, const char *name){	X509 *cert = NULL;	RSA *rsa = NULL, *pub_rsa;	struct cryptoapi_rsa_data *priv;	RSA_METHOD *rsa_meth;	if (name == NULL ||	    (strncmp(name, "cert://", 7) != 0 &&	     strncmp(name, "hash://", 7) != 0))		return -1;	priv = os_zalloc(sizeof(*priv));	rsa_meth = os_zalloc(sizeof(*rsa_meth));	if (priv == NULL || rsa_meth == NULL) {		wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "			   "for CryptoAPI RSA method");		os_free(priv);		os_free(rsa_meth);		return -1;	}	priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);	if (priv->cert == NULL) {		priv->cert = cryptoapi_find_cert(			name, CERT_SYSTEM_STORE_LOCAL_MACHINE);	}	if (priv->cert == NULL) {		wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "			   "'%s'", name);		goto err;	}	cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded,			priv->cert->cbCertEncoded);	if (cert == NULL) {		wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "			   "encoding");		goto err;	}	if (mingw_load_crypto_func())		goto err;	if (!CryptAcquireCertificatePrivateKey(priv->cert,					       CRYPT_ACQUIRE_COMPARE_KEY_FLAG,					       NULL, &priv->crypt_prov,					       &priv->key_spec,					       &priv->free_crypt_prov)) {		cryptoapi_error("Failed to acquire a private key for the "				"certificate");		goto err;	}	rsa_meth->name = "Microsoft CryptoAPI RSA Method";	rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;	rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;	rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;	rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;	rsa_meth->finish = cryptoapi_finish;	rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;	rsa_meth->app_data = (char *) priv;	rsa = RSA_new();	if (rsa == NULL) {		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,		       ERR_R_MALLOC_FAILURE);		goto err;	}	if (!SSL_use_certificate(ssl, cert)) {		RSA_free(rsa);		rsa = NULL;		goto err;	}	pub_rsa = cert->cert_info->key->pkey->pkey.rsa;	X509_free(cert);	cert = NULL;	rsa->n = BN_dup(pub_rsa->n);	rsa->e = BN_dup(pub_rsa->e);	if (!RSA_set_method(rsa, rsa_meth))		goto err;	if (!SSL_use_RSAPrivateKey(ssl, rsa))		goto err;	RSA_free(rsa);	return 0;err:	if (cert)		X509_free(cert);	if (rsa)		RSA_free(rsa);	else {		os_free(rsa_meth);		cryptoapi_free_data(priv);	}	return -1;}static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name){	HCERTSTORE cs;	PCCERT_CONTEXT ctx = NULL;	X509 *cert;	char buf[128];	const char *store;#ifdef UNICODE	WCHAR *wstore;#endif /* UNICODE */	if (mingw_load_crypto_func())		return -1;	if (name == NULL || strncmp(name, "cert_store://", 13) != 0)		return -1;	store = name + 13;#ifdef UNICODE	wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));	if (wstore == NULL)		return -1;	wsprintf(wstore, L"%S", store);	cs = CertOpenSystemStore(0, wstore);	os_free(wstore);#else /* UNICODE */	cs = CertOpenSystemStore(0, store);#endif /* UNICODE */	if (cs == NULL) {		wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "			   "'%s': error=%d", __func__, store,			   (int) GetLastError());		return -1;	}	while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {		cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded,				ctx->cbCertEncoded);		if (cert == NULL) {			wpa_printf(MSG_INFO, "CryptoAPI: Could not process "				   "X509 DER encoding for CA cert");			continue;		}		X509_NAME_oneline(X509_get_subject_name(cert), buf,				  sizeof(buf));		wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "			   "system certificate store: subject='%s'", buf);		if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {			tls_show_errors(MSG_WARNING, __func__,					"Failed to add ca_cert to OpenSSL "					"certificate store");		}		X509_free(cert);	}	if (!CertCloseStore(cs, 0)) {		wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "			   "'%s': error=%d", __func__, name + 13,			   (int) GetLastError());	}	return 0;}#else /* CONFIG_NATIVE_WINDOWS */static int tls_cryptoapi_cert(SSL *ssl, const char *name){	return -1;}#endif /* CONFIG_NATIVE_WINDOWS */static void ssl_info_cb(const SSL *ssl, int where, int ret){

⌨️ 快捷键说明

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