📄 tls_openssl.c
字号:
if (dh_file == NULL) return 0; if (conn == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio);#ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; }#endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_set_tmp_dh(conn->ssl, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0;#endif /* OPENSSL_NO_DH */}int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys){ SSL *ssl; if (conn == NULL || keys == NULL) return -1; ssl = conn->ssl; if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) return -1; memset(keys, 0, sizeof(*keys)); keys->master_key = ssl->session->master_key; keys->master_key_len = ssl->session->master_key_length; keys->client_random = ssl->s3->client_random; keys->client_random_len = SSL3_RANDOM_SIZE; keys->server_random = ssl->s3->server_random; keys->server_random_len = SSL3_RANDOM_SIZE; return 0;}int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len){ return -1;}u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len){ int res; u8 *out_data; /* * Give TLS handshake data from the server (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_connect(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_connect - want " "more data"); else if (err == SSL_ERROR_WANT_WRITE) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to " "write"); else { tls_show_errors(MSG_INFO, __func__, "SSL_connect"); conn->failed++; } } /* Get the TLS handshake data to be sent to the server */ res = BIO_ctrl_pending(conn->ssl_out); wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); out_data = 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;}u8 * tls_connection_server_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len){ int res; u8 *out_data; char buf[10]; 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; } res = SSL_read(conn->ssl, buf, sizeof(buf)); if (res >= 0) { wpa_printf(MSG_DEBUG, "SSL: Unexpected data from SSL_read " "(res=%d)", res); } res = BIO_ctrl_pending(conn->ssl_out); wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); out_data = 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;}#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; if (conn == NULL || conn->pre_shared_secret == 0) return 0; memcpy(secret, conn->pre_shared_secret, conn->pre_shared_secret_len); *secret_len = conn->pre_shared_secret_len; return 1;}int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, const u8 *key, size_t key_len){ if (conn == NULL || key_len > SSL_MAX_MASTER_KEY_LENGTH) return -1; free(conn->pre_shared_secret); conn->pre_shared_secret = NULL; conn->pre_shared_secret_len = 0; if (key) { conn->pre_shared_secret = malloc(key_len); if (conn->pre_shared_secret) { memcpy(conn->pre_shared_secret, key, key_len); conn->pre_shared_secret_len = key_len; } if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, conn) != 1) return -1; } else { if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) return -1; } return 0;}#endif /* EAP_FAST || EAP_FAST_DYNAMIC */int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL || conn->ssl == NULL) return -1; if (SSL_set_cipher_list(conn->ssl, "ADH-AES128-SHA") != 1) { tls_show_errors(MSG_INFO, __func__, "Anon DH 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; snprintf(buf, buflen, "%s", name); 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) return -1; if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, data_len) != 1) return -1; 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 (tls_connection_set_subject_match(conn, params->subject_match, params->altsubject_match)) return -1; 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 (tls_connection_client_cert(conn, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) return -1; if (params->engine) { wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); ret = tls_engine_init(conn, params->engine_id, params->pin, params->key_id); if (ret) return ret; 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; 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; h = conn->ssl->read_hash; 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -