📄 tls_openssl.c
字号:
/* * Give TLS handshake data from the client (if available) to OpenSSL * for processing. */ if (in_data && BIO_write(conn->ssl_in, in_data, in_len) < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_write"); return NULL; } /* Initiate TLS handshake or continue the existing handshake */ res = SSL_accept(conn->ssl); if (res != 1) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ) wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want " "more data"); else if (err == SSL_ERROR_WANT_WRITE) wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to " "write"); else { tls_show_errors(MSG_INFO, __func__, "SSL_accept"); return NULL; } } /* Get the TLS handshake data to be sent to the client */ res = BIO_ctrl_pending(conn->ssl_out); wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); out_data = os_malloc(res == 0 ? 1 : res); if (out_data == NULL) { wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " "handshake output (%d bytes)", res); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } *out_len = 0; return NULL; } res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_read"); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } *out_len = 0; return NULL; } *out_len = res; return out_data;}int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len){ int res; if (conn == NULL) return -1; /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */ if ((res = BIO_reset(conn->ssl_in)) < 0 || (res = BIO_reset(conn->ssl_out)) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return res; } res = SSL_write(conn->ssl, in_data, in_len); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - SSL_write"); return res; } /* Read encrypted data to be sent to the server */ res = BIO_read(conn->ssl_out, out_data, out_len); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - BIO_read"); return res; } return res;}int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len){ int res; /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ res = BIO_write(conn->ssl_in, in_data, in_len); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - BIO_write"); return res; } if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return res; } /* Read decrypted data for further processing */ res = SSL_read(conn->ssl, out_data, out_len); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - SSL_read"); return res; } return res;}int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn){ return conn ? conn->ssl->hit : 0;}int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers){ char buf[100], *pos, *end; u8 *c; int ret; if (conn == NULL || conn->ssl == NULL || ciphers == NULL) return -1; buf[0] = '\0'; pos = buf; end = pos + sizeof(buf); c = ciphers; while (*c != TLS_CIPHER_NONE) { const char *suite; switch (*c) { case TLS_CIPHER_RC4_SHA: suite = "RC4-SHA"; break; case TLS_CIPHER_AES128_SHA: suite = "AES128-SHA"; break; case TLS_CIPHER_RSA_DHE_AES128_SHA: suite = "DHE-RSA-AES128-SHA"; break; case TLS_CIPHER_ANON_DH_AES128_SHA: suite = "ADH-AES128-SHA"; break; default: wpa_printf(MSG_DEBUG, "TLS: Unsupported " "cipher selection: %d", *c); return -1; } ret = os_snprintf(pos, end - pos, ":%s", suite); if (ret < 0 || ret >= end - pos) break; pos += ret; c++; } wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) { tls_show_errors(MSG_INFO, __func__, "Cipher suite configuration failed"); return -1; } return 0;}int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen){ const char *name; if (conn == NULL || conn->ssl == NULL) return -1; name = SSL_get_cipher(conn->ssl); if (name == NULL) return -1; os_strlcpy(buf, name, buflen); return 0;}int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn){ SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); return 0;}#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)/* ClientHello TLS extensions require a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len){ if (conn == NULL || conn->ssl == NULL || ext_type != 35) return -1;#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE if (SSL_set_session_ticket_ext(conn->ssl, (void *) data, data_len) != 1) return -1;#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, data_len) != 1) return -1;#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ return 0;}#endif /* EAP_FAST || EAP_FAST_DYNAMIC */int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; return conn->failed;}int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; return conn->read_alerts;}int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; return conn->write_alerts;}int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params){ int ret; unsigned long err; if (conn == NULL) return -1; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (params->engine) { wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); ret = tls_engine_init(conn, params->engine_id, params->pin, params->key_id, params->cert_id, params->ca_cert_id); if (ret) return ret; } if (tls_connection_set_subject_match(conn, params->subject_match, params->altsubject_match)) return -1; if (params->engine && params->ca_cert_id) { if (tls_connection_engine_ca_cert(tls_ctx, conn, params->ca_cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) return -1; if (params->engine && params->cert_id) { if (tls_connection_engine_client_cert(conn, params->cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_client_cert(conn, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) return -1; if (params->engine && params->key_id) { wpa_printf(MSG_DEBUG, "TLS: Using private key from engine"); if (tls_connection_engine_private_key(conn)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_private_key(tls_ctx, conn, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", params->private_key); return -1; } if (tls_connection_dh(conn, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } tls_get_errors(tls_ctx); return 0;}int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params){ SSL_CTX *ssl_ctx = tls_ctx; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (tls_global_ca_cert(ssl_ctx, params->ca_cert)) return -1; if (tls_global_client_cert(ssl_ctx, params->client_cert)) return -1; if (tls_global_private_key(ssl_ctx, params->private_key, params->private_key_passwd)) return -1; if (tls_global_dh(ssl_ctx, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } return 0;}int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn){ const EVP_CIPHER *c; const EVP_MD *h; if (conn == NULL || conn->ssl == NULL || conn->ssl->enc_read_ctx == NULL || conn->ssl->enc_read_ctx->cipher == NULL || conn->ssl->read_hash == NULL) return -1; c = conn->ssl->enc_read_ctx->cipher;#if OPENSSL_VERSION_NUMBER >= 0x00909000L h = EVP_MD_CTX_md(conn->ssl->read_hash);#else h = conn->ssl->read_hash;#endif return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) + EVP_CIPHER_iv_length(c));}unsigned int tls_capabilities(void *tls_ctx){ return 0;}int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia){ return -1;}int tls_connection_ia_send_phase_finished(void *tls_ctx, struct tls_connection *conn, int final, u8 *out_data, size_t out_len){ return -1;}int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn){ return -1;}int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len){ return -1;}#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)/* Pre-shared secred requires a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg){ struct tls_connection *conn = arg; int ret; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, s->s3->client_random, s->s3->server_random, secret); os_free(conn->session_ticket); conn->session_ticket = NULL; if (ret <= 0) return 0; *secret_len = SSL_MAX_MASTER_KEY_LENGTH; return 1;}#ifdef CONFIG_OPENSSL_TICKET_OVERRIDEstatic int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data, int len, void *arg){ struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len); os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_malloc(len); if (conn->session_ticket == NULL) return 0; os_memcpy(conn->session_ticket, data, len); conn->session_ticket_len = len; return 1;}#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */#ifdef SSL_OP_NO_TICKETstatic void tls_hello_ext_cb(SSL *s, int client_server, int type, unsigned char *data, int len, void *arg){ struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return; wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, type, len); if (type == TLSEXT_TYPE_session_ticket && !client_server) { os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_malloc(len); if (conn->session_ticket == NULL) return; os_memcpy(conn->session_ticket, data, len); conn->session_ticket_len = len; }}#else /* SSL_OP_NO_TICKET */static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg){ struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, ext->type, ext->length); os_free(conn->session_ticket); conn->session_ticket = NULL; if (ext->type == 35) { wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", ext->data, ext->length); conn->session_ticket = os_malloc(ext->length); if (conn->session_ticket == NULL) return SSL_AD_INTERNAL_ERROR; os_memcpy(conn->session_ticket, ext->data, ext->length); conn->session_ticket_l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -